android应用开发 - 沈大海

116
LAMP 人 人人人人人人人 www.LAMPER.cn QQ 人3330312 http://weibo.com/lampercn

Upload: shaoning-pan

Post on 10-May-2015

1.530 views

Category:

Technology


3 download

DESCRIPTION

Android应用开发 - 沈大海

TRANSCRIPT

Page 1: Android应用开发 - 沈大海

LAMP 人 主题分享交流会

wwwLAMPERcnQQ 群 3330312

httpweibocomlampercn

Android 开发技术培训

沈大海

知识大纲bull Android 手机空间划分bull Android Frameworkbull Android SDKNDK 开发环境搭建bull Android Application 分析bull Android Loop Handler 机制bull Android 应用开发基本组件使用bull 实现 AIDL 定义远程通讯 Servicebull 实现 WidgetWallpaperbull Google Map 开发bull LocaltionManagerbull 使用 NDK 开发bull 开源引擎 Cocos2d-x 介绍bull 开发优化

Android 手机软硬件形态

Android Framework5

Android 体系结构bull 应用程序 (Applications) 依据 User 的期望而将 AF 的组件及

Libaraies 组件组合而成的高阶服务bull 应用框架 (Application Framework 简称 AF) 这是结合

Applications与 Libraries 的幕后主架构让 Libraries 组件能不断地为 Applications 所重复使用 (Reuse)

bull 丰富而又可扩展的视图( Views )bull 内容提供器( Content Providers )bull 资源管理器( Resource Manager )bull 通知管理器 ( Notification Manager )bull 活动管理器( Activity Manager )

bull Libraries Android 里已经提供的 CC++ 库存组件 ( 或称模块 ) 例如 SQLite 数据库系统 OpenGL 3D 绘图系统等

bull Android Runtime Java 语言层级的 Virtual Machine bull Linux 核心 Android 依赖 Linux 26 来提供核心的服务例如内存

管理进程 (Process) 管理执行绪 (Thread) 管理等

6

Android层次 -kernel

Android基于 Linux 26提供核心系统服务例如安全内存管理进程管理网络堆栈驱动模型 Linux Kernel也作为硬件和软件之间的抽象层它隐藏具体硬件细节而为上层提供统一的服务

使用 binder作为进程间通讯机制取代传统进程间通讯机制

7

Linux KernelLinux KernelDisplay Driver

Camera Driver

Flash Driver

SD Driver

Keypad Driver

Touch Driver

USB Driver

PM

Common Kernel(File System

Networking etc)

HardwareHardwareCamera

ISPTouchCPU

MVED Driver

GCU Driver

MM Accelerate

BatteryCharging

RTC Alarm

Modem

IPC Driver

WIFIBT

Android Enhancement(Binder Ash

Log ADB etc) Sensors Driver

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 2: Android应用开发 - 沈大海

Android 开发技术培训

沈大海

知识大纲bull Android 手机空间划分bull Android Frameworkbull Android SDKNDK 开发环境搭建bull Android Application 分析bull Android Loop Handler 机制bull Android 应用开发基本组件使用bull 实现 AIDL 定义远程通讯 Servicebull 实现 WidgetWallpaperbull Google Map 开发bull LocaltionManagerbull 使用 NDK 开发bull 开源引擎 Cocos2d-x 介绍bull 开发优化

Android 手机软硬件形态

Android Framework5

Android 体系结构bull 应用程序 (Applications) 依据 User 的期望而将 AF 的组件及

Libaraies 组件组合而成的高阶服务bull 应用框架 (Application Framework 简称 AF) 这是结合

Applications与 Libraries 的幕后主架构让 Libraries 组件能不断地为 Applications 所重复使用 (Reuse)

bull 丰富而又可扩展的视图( Views )bull 内容提供器( Content Providers )bull 资源管理器( Resource Manager )bull 通知管理器 ( Notification Manager )bull 活动管理器( Activity Manager )

bull Libraries Android 里已经提供的 CC++ 库存组件 ( 或称模块 ) 例如 SQLite 数据库系统 OpenGL 3D 绘图系统等

bull Android Runtime Java 语言层级的 Virtual Machine bull Linux 核心 Android 依赖 Linux 26 来提供核心的服务例如内存

管理进程 (Process) 管理执行绪 (Thread) 管理等

6

Android层次 -kernel

Android基于 Linux 26提供核心系统服务例如安全内存管理进程管理网络堆栈驱动模型 Linux Kernel也作为硬件和软件之间的抽象层它隐藏具体硬件细节而为上层提供统一的服务

使用 binder作为进程间通讯机制取代传统进程间通讯机制

7

Linux KernelLinux KernelDisplay Driver

Camera Driver

Flash Driver

SD Driver

Keypad Driver

Touch Driver

USB Driver

PM

Common Kernel(File System

Networking etc)

HardwareHardwareCamera

ISPTouchCPU

MVED Driver

GCU Driver

MM Accelerate

BatteryCharging

RTC Alarm

Modem

IPC Driver

WIFIBT

Android Enhancement(Binder Ash

Log ADB etc) Sensors Driver

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 3: Android应用开发 - 沈大海

知识大纲bull Android 手机空间划分bull Android Frameworkbull Android SDKNDK 开发环境搭建bull Android Application 分析bull Android Loop Handler 机制bull Android 应用开发基本组件使用bull 实现 AIDL 定义远程通讯 Servicebull 实现 WidgetWallpaperbull Google Map 开发bull LocaltionManagerbull 使用 NDK 开发bull 开源引擎 Cocos2d-x 介绍bull 开发优化

Android 手机软硬件形态

Android Framework5

Android 体系结构bull 应用程序 (Applications) 依据 User 的期望而将 AF 的组件及

Libaraies 组件组合而成的高阶服务bull 应用框架 (Application Framework 简称 AF) 这是结合

Applications与 Libraries 的幕后主架构让 Libraries 组件能不断地为 Applications 所重复使用 (Reuse)

bull 丰富而又可扩展的视图( Views )bull 内容提供器( Content Providers )bull 资源管理器( Resource Manager )bull 通知管理器 ( Notification Manager )bull 活动管理器( Activity Manager )

bull Libraries Android 里已经提供的 CC++ 库存组件 ( 或称模块 ) 例如 SQLite 数据库系统 OpenGL 3D 绘图系统等

bull Android Runtime Java 语言层级的 Virtual Machine bull Linux 核心 Android 依赖 Linux 26 来提供核心的服务例如内存

管理进程 (Process) 管理执行绪 (Thread) 管理等

6

Android层次 -kernel

Android基于 Linux 26提供核心系统服务例如安全内存管理进程管理网络堆栈驱动模型 Linux Kernel也作为硬件和软件之间的抽象层它隐藏具体硬件细节而为上层提供统一的服务

使用 binder作为进程间通讯机制取代传统进程间通讯机制

7

Linux KernelLinux KernelDisplay Driver

Camera Driver

Flash Driver

SD Driver

Keypad Driver

Touch Driver

USB Driver

PM

Common Kernel(File System

Networking etc)

HardwareHardwareCamera

ISPTouchCPU

MVED Driver

GCU Driver

MM Accelerate

BatteryCharging

RTC Alarm

Modem

IPC Driver

WIFIBT

Android Enhancement(Binder Ash

Log ADB etc) Sensors Driver

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 4: Android应用开发 - 沈大海

Android 手机软硬件形态

Android Framework5

Android 体系结构bull 应用程序 (Applications) 依据 User 的期望而将 AF 的组件及

Libaraies 组件组合而成的高阶服务bull 应用框架 (Application Framework 简称 AF) 这是结合

Applications与 Libraries 的幕后主架构让 Libraries 组件能不断地为 Applications 所重复使用 (Reuse)

bull 丰富而又可扩展的视图( Views )bull 内容提供器( Content Providers )bull 资源管理器( Resource Manager )bull 通知管理器 ( Notification Manager )bull 活动管理器( Activity Manager )

bull Libraries Android 里已经提供的 CC++ 库存组件 ( 或称模块 ) 例如 SQLite 数据库系统 OpenGL 3D 绘图系统等

bull Android Runtime Java 语言层级的 Virtual Machine bull Linux 核心 Android 依赖 Linux 26 来提供核心的服务例如内存

管理进程 (Process) 管理执行绪 (Thread) 管理等

6

Android层次 -kernel

Android基于 Linux 26提供核心系统服务例如安全内存管理进程管理网络堆栈驱动模型 Linux Kernel也作为硬件和软件之间的抽象层它隐藏具体硬件细节而为上层提供统一的服务

使用 binder作为进程间通讯机制取代传统进程间通讯机制

7

Linux KernelLinux KernelDisplay Driver

Camera Driver

Flash Driver

SD Driver

Keypad Driver

Touch Driver

USB Driver

PM

Common Kernel(File System

Networking etc)

HardwareHardwareCamera

ISPTouchCPU

MVED Driver

GCU Driver

MM Accelerate

BatteryCharging

RTC Alarm

Modem

IPC Driver

WIFIBT

Android Enhancement(Binder Ash

Log ADB etc) Sensors Driver

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 5: Android应用开发 - 沈大海

Android Framework5

Android 体系结构bull 应用程序 (Applications) 依据 User 的期望而将 AF 的组件及

Libaraies 组件组合而成的高阶服务bull 应用框架 (Application Framework 简称 AF) 这是结合

Applications与 Libraries 的幕后主架构让 Libraries 组件能不断地为 Applications 所重复使用 (Reuse)

bull 丰富而又可扩展的视图( Views )bull 内容提供器( Content Providers )bull 资源管理器( Resource Manager )bull 通知管理器 ( Notification Manager )bull 活动管理器( Activity Manager )

bull Libraries Android 里已经提供的 CC++ 库存组件 ( 或称模块 ) 例如 SQLite 数据库系统 OpenGL 3D 绘图系统等

bull Android Runtime Java 语言层级的 Virtual Machine bull Linux 核心 Android 依赖 Linux 26 来提供核心的服务例如内存

管理进程 (Process) 管理执行绪 (Thread) 管理等

6

Android层次 -kernel

Android基于 Linux 26提供核心系统服务例如安全内存管理进程管理网络堆栈驱动模型 Linux Kernel也作为硬件和软件之间的抽象层它隐藏具体硬件细节而为上层提供统一的服务

使用 binder作为进程间通讯机制取代传统进程间通讯机制

7

Linux KernelLinux KernelDisplay Driver

Camera Driver

Flash Driver

SD Driver

Keypad Driver

Touch Driver

USB Driver

PM

Common Kernel(File System

Networking etc)

HardwareHardwareCamera

ISPTouchCPU

MVED Driver

GCU Driver

MM Accelerate

BatteryCharging

RTC Alarm

Modem

IPC Driver

WIFIBT

Android Enhancement(Binder Ash

Log ADB etc) Sensors Driver

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 6: Android应用开发 - 沈大海

Android 体系结构bull 应用程序 (Applications) 依据 User 的期望而将 AF 的组件及

Libaraies 组件组合而成的高阶服务bull 应用框架 (Application Framework 简称 AF) 这是结合

Applications与 Libraries 的幕后主架构让 Libraries 组件能不断地为 Applications 所重复使用 (Reuse)

bull 丰富而又可扩展的视图( Views )bull 内容提供器( Content Providers )bull 资源管理器( Resource Manager )bull 通知管理器 ( Notification Manager )bull 活动管理器( Activity Manager )

bull Libraries Android 里已经提供的 CC++ 库存组件 ( 或称模块 ) 例如 SQLite 数据库系统 OpenGL 3D 绘图系统等

bull Android Runtime Java 语言层级的 Virtual Machine bull Linux 核心 Android 依赖 Linux 26 来提供核心的服务例如内存

管理进程 (Process) 管理执行绪 (Thread) 管理等

6

Android层次 -kernel

Android基于 Linux 26提供核心系统服务例如安全内存管理进程管理网络堆栈驱动模型 Linux Kernel也作为硬件和软件之间的抽象层它隐藏具体硬件细节而为上层提供统一的服务

使用 binder作为进程间通讯机制取代传统进程间通讯机制

7

Linux KernelLinux KernelDisplay Driver

Camera Driver

Flash Driver

SD Driver

Keypad Driver

Touch Driver

USB Driver

PM

Common Kernel(File System

Networking etc)

HardwareHardwareCamera

ISPTouchCPU

MVED Driver

GCU Driver

MM Accelerate

BatteryCharging

RTC Alarm

Modem

IPC Driver

WIFIBT

Android Enhancement(Binder Ash

Log ADB etc) Sensors Driver

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 7: Android应用开发 - 沈大海

Android层次 -kernel

Android基于 Linux 26提供核心系统服务例如安全内存管理进程管理网络堆栈驱动模型 Linux Kernel也作为硬件和软件之间的抽象层它隐藏具体硬件细节而为上层提供统一的服务

使用 binder作为进程间通讯机制取代传统进程间通讯机制

7

Linux KernelLinux KernelDisplay Driver

Camera Driver

Flash Driver

SD Driver

Keypad Driver

Touch Driver

USB Driver

PM

Common Kernel(File System

Networking etc)

HardwareHardwareCamera

ISPTouchCPU

MVED Driver

GCU Driver

MM Accelerate

BatteryCharging

RTC Alarm

Modem

IPC Driver

WIFIBT

Android Enhancement(Binder Ash

Log ADB etc) Sensors Driver

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 8: Android应用开发 - 沈大海

Android ndash Hardware Abstraction Layer

用户空间的 CC++库遵循 Apache协议定义 Android需要 linux driver实现的接口将 Android彻底和硬件抽象出来

8

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 9: Android应用开发 - 沈大海

Android层次结构 -Android Runtime

Android包含一个核心库的集合提供大部分在 Java编程语言核心类库中可用的功能Dalvik虚拟机则是基于寄存器的而非大多数 虚拟机所采用的基于栈的实现Dalvik虚拟机依赖于 Linux 内核提供基本功能 如线程和底层内存管理

9

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 10: Android应用开发 - 沈大海

Android包含一个 CC++库的集合供 Android系统的各个组件使用这些功能通过 Android的应用程序框架( application framework)暴露给开发者下面列出一些核心库系统 C库多媒体库 OpenCore界面管理LibWebCoreSGL3D库FreeTypeSQLite

Android层次结构 -Libraries10

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 11: Android应用开发 - 沈大海

Android层次结构- Application Framework

通过提供开放的开发平台 Android使开发者能够编制极其丰富和新颖的应用程序开发者可以自由地利用设备硬件优势访问位置信息运行后台服务设置闹钟向状态栏添加通知等等很多很多开发者可以完全使用核心应用程序所使用的框架 APIs应用程序的体系结构旨在简化组件的重用任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功

能(需要服从框架执行的安全限制)这一机制允许用户替换组件 所有的应用程序其实是一组服务和系统包括ViewActivityManagerContentProviderNotificationManager

11

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 12: Android应用开发 - 沈大海

Android层次结构- Applications

Android魅力的终极体现 对用户良好的用户体验强大的用户亲和力 对开发者快速而灵活的开发平台让开发者的灵感能快速转化为产品

12

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 13: Android应用开发 - 沈大海

Android 进程运行

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 14: Android应用开发 - 沈大海

基本开发方向 -Android 移植集成所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroid python 使用Androidbuildtools

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 15: Android应用开发 - 沈大海

基本开发方向 - 应用开发

所需知识

Android 核心组件Android UI 组件Android GUI 编程Android 事件处理NDK 开发OpenGL 开发

编译工具EclipseJava C 语言

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 16: Android应用开发 - 沈大海

基本开发方向mdash Android 系统开发所需知识 Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库Dalvik 虚拟机 Android GUI 系统音频视频和多媒体 电话部分的连接部分传感器部分

编译工具Vim 或者 EmacsAndroid Shell 脚本Android makefileAndroidbuildtoolsJava 开发JNI 技术

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 17: Android应用开发 - 沈大海

三种开发形式bull SDK 开发

ndash Windows linux mac

bull NDK 开发ndash Windows linux

bull 源码开发ndash (完全源代码 Linux 中开发)

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 18: Android应用开发 - 沈大海

Android Applications

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 19: Android应用开发 - 沈大海

Android apk build and packaging

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 20: Android应用开发 - 沈大海

Android application unpackaging and run

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 21: Android应用开发 - 沈大海

AAPT 打包示意图21

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 22: Android应用开发 - 沈大海

限定符的类型和有效的值 限定符 有效值语言 语言码遵循 ISO 639-1 标准小写如 en zh

地区 遵循 ISO 3166-1-alpha-2 标准大写前面加小写的ldquo rrdquo 例如 rUS rCN

屏幕朝向 port land square

屏幕像素密度 92dpi 108dpi 等触摸屏类型 notouch stylus finger

键盘是否可用 keysexposed keyshidden

首选的输入法 nokeys qwerty 12key

首选非触摸导航方法 nonav dpad trackball wheel

屏幕尺寸 320x240 640x480 等大尺寸必须在前

22

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 23: Android应用开发 - 沈大海

资源管理框架23

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 24: Android应用开发 - 沈大海

Activity 介绍

l展现为一个用户可视化界面lActivity可以多种形式呈现如全屏模式对话框模式透明模式等lActivity的部分重要属性

l androidlabel=string resource l androidicon=drawable resource l androidlaunchMode=[multiple | singleTop |singleTask | singleInstance]

24

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 25: Android应用开发 - 沈大海

基础 UI

bull menu 如何打造友好的菜单bull ListView 用好列表做好程序bull Dialog 人机友好互动交流bull Toast和 Notification 温馨的提醒bull 各种 View 组件bull 自定义 View 组件

25

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 26: Android应用开发 - 沈大海

Application ui description

通过绑定 Activity的 setContentView() 方法在 onResume 之后绘制

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 27: Android应用开发 - 沈大海

A tree-structure ui

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 28: Android应用开发 - 沈大海

Viewwindows base

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 29: Android应用开发 - 沈大海

图形系统层次结构

Android Apps

Application Framework

Native Libraries

HAL

SurfaceFlinger

Activity Manager Window ManagerView System

Display Driver(FrameBuffer)

View ---- Image Shape Text Animation Canvas

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 30: Android应用开发 - 沈大海

2D graphics processActivity

androidviewandroidgraphics(Canvas PaintPathPictureRegion)

ActivityManagerWindowManager

frameworksbasecorejniandroidgraphic

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

externalskia

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 31: Android应用开发 - 沈大海

3D graphics processActivity

androidopengljavaxmicroeditionkhronosegljavaxmicroeditionkhronosopengl(GLSurfaceView)

ActivityManagerWindowManager

frameworksgles_jni

SurfaceFlinger

HAL FrameBuffer

Get Surface Obj

frameworksbaseopengl

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 32: Android应用开发 - 沈大海

Android 图形系统 GUI includeJava --- androidgraphics (Skia lib draw feature) androidviewsurface androidviewview javaxmicroeditionkhronosopengles androidopenglCC++ --PixelFlinger (tool lib) libui SurfaceFlinger Skia Opengles 3D

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 33: Android应用开发 - 沈大海

Android 图形系统

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 34: Android应用开发 - 沈大海

Android- 动画tween

对 view 的内容进行一系列变换 ( 平移 缩放 渐变 )

frame

顺序播放一组图片 达到动画的效果

动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类

渐变透明度动画效果 ltalphagt AlphaAnimation

渐变尺寸缩放动画效果 ltscalegt ScaleAnimation

画面位置移动动画效果 lttranslategt TranslateAnimation

画面旋转动画效果 ltrotategt RotateAnimation

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 35: Android应用开发 - 沈大海

Android- 动画 ( 缩放 )定义动画文件 resanimscalexml

ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltscale

androidinterpolator=androidanimaccelerate_decelerate

_interpolator

androidfromXScale=00 起始时 X 轴比例 ( 相较于图片本身 )

androidfromYScale=00

androidtoXScale=5 结束时 y 轴上的比例androidtoYScale=5

androidpivotX=50 x 轴轴心androidpivotY=50 y 轴轴心androidfillAfter=false 为 true 该动画转化在动画结束后被应用androidduration=5000gt 持续时间 (毫秒 )

ltsetgt

注 LinearInterpolatorAccelerateinterpolatorDecelerateInterpolator

自定义

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 36: Android应用开发 - 沈大海

Android- 动画 ( 缩放 )定义布局文件ltImageView

androidlayout_width=wrap_content

androidlayout_height=wrap_content

androidsrc=drawableicon

androidid=+idimageViewgt

加载动画 XML 文件 生成动画指令Animation animation = AnimationUtilsloadAnimation(this Ranimscale)

开始执行动画imageViewstartAnimation(animation)

编程式ScaleAnimation animation = new ScaleAnimation(00f 5f 00f 5f

AnimationRELATIVE_TO_SELF 05f

AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 37: Android应用开发 - 沈大海

Android- 动画 ( 透明 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltalpha

androidfromAlpha=01

androidtoAlpha=10

androidduration=3000gt

ltsetgt

AlphaAnimation animation = new AlphaAnimation(01 10)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 38: Android应用开发 - 沈大海

Android- 动画 ( 移动 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

lttranslate

androidrepeatCount=2

androidfromXDelta=0

androidfromYDelta=0

androidtoXDelta=120

androidtoYDelta=120

androidduration=3000gt

ltsetgt

TranslateAnimation animation = new TranslateAnimation(0 120 0 120)

animationsetDuration(5000) 设置持续时间 5秒imageViewstartAnimation(animation)

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 39: Android应用开发 - 沈大海

Android- 动画 ( 旋转 )ltxml version=10 encoding=utf-8gt

ltset xmlnsandroid=httpschemasandroidcomapkresandroidgt

ltrotate

androidinterpolator=androidanimaccelerate_interpolator

androidrepeatCount=2

androidfromDegrees=0

androidtoDegrees=+360

androidpivotX=50

androidpivotY=50

androidduration=3000gt

ltsetgt

RotateAnimation animation = new RotateAnimation(0 -90 AnimationRELATIVE_TO_SELF 05f AnimationRELATIVE_TO_SELF 05f)

animationsetDuration(500)

imageViewstartAnimation(animation)

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 40: Android应用开发 - 沈大海

Android- 动画 (frame)准备图片 resdrawable1gif 2gif

resaniframexml

ltxml version=10 encoding=utf-8gt

ltanimation-list

xmlnsandroid=httpschemasandroidcomapkresandroid

androidoneshot=falsegt

ltitem androiddrawable=drawablegirl_1 androidduration=200 gt

ltitem androiddrawable=drawablegirl_3 androidduration=200 gt

ltanimation-listgt

imageViewsetBackgroundResource(Ranimframe)

animationDrawable = (AnimationDrawable) imageViewgetBackground()

public boolean onTouchEvent(MotionEvent event)

if (eventgetAction() == MotionEventACTION_DOWN) 按下animationDrawablestart()

return true

return superonTouchEvent(event)

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 41: Android应用开发 - 沈大海

事件处理ndash onKeyDownndash onTouchEvent

bull Activityndash onResume 后

bull Viewndash设为焦点

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 42: Android应用开发 - 沈大海

Android- 手势识别添加视图监听器

gestureOverlayViewaddOnGesturePerformedListener()

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

mLibraryload()

gestureOverlayView = thisfindViewById(Ridgestures)

gestureOverlayViewaddOnGesturePerformedListener(GestureListener())

mLibrary = GestureLibrariesfromRawResource(this Rrawgestures)

state = mLibraryload() 加载手势库

interface GestureOverlayViewOnGesturePerformedListener

public void onGesturePerformed(GestureOverlayView oGesture g)

ListltPredictiongt=mLibraryrecognize(gesture)

Prediction prediction = predictionsget(0)

predictionscore0-100

predictionname名称

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 43: Android应用开发 - 沈大海

Android- 传感器传感器类型方向传感器 SensorTYPE_ORIENTATION

加速度 ( 重力 ) 传感器 SensorTYPE_ACCELEROMETER

光线传感器 SensorTYPE_LIGHT

磁场传感器 SensorTYPE_MAGNETIC_FIELD

距离 (临近性 ) 传感器 SensorTYPE_PROXIMITY

温度传感器 SensorTYPE_TEMPERATURE

获取传感器Sensor sensor =

sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

注册监听 获取传感器变化值sensorManagerregisterListener(listener sensor

SensorManagerSENSOR_DELAY_GAME)

上面第三个参数为采样率 最快 游戏 普通 用户界面 当应用程序请求特定的采样率时 其实只是对传感器子系统的一个建议 不保证特定的采样率可用

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 44: Android应用开发 - 沈大海

Android- 传感器 获取感应器管理器sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE)

accelerometer = (TextView) findViewById(Ridaccelerometer)

orientation = (TextView) findViewById(Ridorientation)

protected void onResume()

获取重力加速度传感器Sensor sensor = sensorManagergetDefaultSensor(SensorTYPE_ACCELEROMETER)

sensorManagerregisterListener(listener sensor SensorManagerSENSOR_DELAY_GAME)

获取方向传感器Sensor sensor1 = sensorManagergetDefaultSensor(SensorTYPE_ORIENTATION)

sensorManagerregisterListener(listener sensor1SensorManagerSENSOR_DELAY_GAME)

superonResume()

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 45: Android应用开发 - 沈大海

Android- 传感器注册监听器private SensorEventListener listener = new SensorEventListener()

public void onSensorChanged(SensorEvent event) float x = eventvalues[SensorManagerDATA_X]

float y = eventvalues[SensorManagerDATA_Y]

float z = eventvalues[SensorManagerDATA_Z]

switch (eventsensorgetType())

case SensorTYPE_ACCELEROMETER

break

case SensorTYPE_ORIENTATION

break

public void onAccuracyChanged(Sensor sensor int accuracy)

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 46: Android应用开发 - 沈大海

Android Application

bull Application就是 Activity Service 之类的组件上下文描述

bull Activity Broadcast Intent Receiver 服务( Service )内容提供器( Content Provider )这些组件依附于应用程序中

bull 应用程序并不会一开始就建立起来而是在这些组件建立起来后需要运行时才开始建立应用程序对象

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 47: Android应用开发 - 沈大海

Activity 所绑定的进程名称bull androidname=string bull androidprocess=string bull Activity Manager Service 在应用程序的第一个组件需要运

行时将会为应用程序建立一个进程而这个进程的名字就是 androidprocess=rdquostringrdquo 所指定缺省的是应用程序包的名字

bull 在建立 Actvitiy 时如果在应用进程端没有应用对象系统在该过程中利用 makeApplication 建立一个 Application对象实例化 androidappApplication 建立一个应用程序上下文完成例如资源 package 等信息管理

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 48: Android应用开发 - 沈大海

进程与生命周期bull Android 系统会尽可能长的延续一个应用程序进程但在内存过低的时候仍然会不可避免需要移除旧的进程为决定保留或移除一个进程 Android 将每个

进程都放入一个ldquo重要性层次rdquo中依据则是它其中运行着的组件及其状态重要性最低的进程首先被消灭然后是较低的依此类推重要性共分五层依据重要性列表如下

bull 1 前台进程bull 是用户操作所必须的当满足如下任一条件时进程被认为是处于前台的 bull 任一时间下仅有少数进程会处于前台仅当内存实在无法供给它们维持同时运行时才会被杀死一般来说在这种情况下设备已然处于使用虚拟内存的

状态必须要杀死一些前台进程以用户界面保持响应bull 2 可视进程bull 没有前台组件但仍可被用户在屏幕上所见当满足如下任一条件时进程被认为是可视的bull o 它包含着一个不在前台但仍然为用户可见的 activity (它的 onPause() 方法被调用)这种情况可能出现在以下情况比如说前台 activity

是一个对话框而之前的 activity 位于其下并可以看到 bull o 它包含了一个绑定至一个可视的 activity 的服务bull 可视进程依然被视为是很重要的非到不杀死它们便无法维持前台进程运行时才会被杀死bull 3 服务进程bull 是由 startService() 方法启动的服务它不会变成上述两类尽管服务进程不会直接为用户所见但它们一般都在做着用户所关心的事情(比如在后台播放

mp3 或者从网上下载东西)所以系统会尽量维持它们的运行除非系统内存不足以维持前台进程和可视进程的运行需要bull 4 背景进程bull 包含目前不为用户所见的 activity( Activity对象的 onStop() 方法已被调用)这些进程与用户体验没有直接的联系可以在任意时间被杀死以回收内存供

前台进程可视进程以及服务进程使用一般来说会有很多背景进程运行所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的activity最后被杀死如果一个 activity正确的实现了生命周期方法并捕获了正确的状态则杀死它的进程对用户体验不会有任何不良影响

bull 5 空进程bull 不包含任何活动应用程序组件这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间系统经常会杀死这种进程以保持进程缓存和

系统内核缓存之间的平衡bull Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别比如说如果一个进程中同时有一个服务和一个可视的 activity 则进程

会被判定为可视进程而不是服务进程bull 此外一个进程的级别可能会由于其它进程依赖于它而升高一个为其它进程提供服务的进程级别永远高于使用它服务的进程比如说如果 A 进程中的内

容提供者为进程 B 中的客户端提供服务或进程 A 中的服务为进程 B 中的组件所绑定则 A 进程最低也会被视为与进程 B拥有同样的重要性

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 49: Android应用开发 - 沈大海

ActivityThreadbull 应用进程不是 Application 而是 ActivityThread 从实际的应用堆栈可以看到

bull NaiveStartmain()bull ZygoteInitmainbull ZygoteInit$MethodAndArgsCallrunbull MethodInvokebull methodinvokeNativebull ActivityThreadmain()bull Looperloop()

bull 每个应用程序都以 ActivityThreadmain()为入口进入到消息循环处理 bull 应用程序通过 ActivityThread 提供的框架建立消息循环 Looper和 Handlerbull ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 50: Android应用开发 - 沈大海

默认的线程为主线程主线程负责 UI 及事件处理每个线程中都有一个 Looper 循环处理本线程的消息队列线程之间通过消息通讯主线程中也可以创建辅助线程但辅助线程不能直接操作 UI 可以线程中创建 Looper 通过消息进行

进程中的线程

APK PackageProcess

ThreadLooper

Message Queue

ThreadExternal Service

Calls

IntentReceiver

Activity

Activity

UI Events

System Events

Local Service

Call

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 51: Android应用开发 - 沈大海

Android消息系统 Loop Handler bull Android消息系统使用了 LooperMessageQueueHandler 等概念 Handler 先进先出原则 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange)

ndash Looper 一个线程可以产生一个 Looper对象由它来管理此线程里的 Message Queue(消息队列 ) Looper只是产生一个消息循环框架首先 Looper创建了消息队列并把它挂接在Linux 的线程上下文中进入到取消息并分发消息的循环当中

ndash Handler Handler对象在同一个线程上下文中取得消息队列对消息队列进行封装操作最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作外部系统需要向某个Android线程发送消息必须通过属于该 AndroidThread的 Handler 这个对象进行

ndash Message Queue(消息队列 ) 用来存放线程放入的消息ndash 线程 UI thread 通常就是 main thread 而 Android启动程序时会替它建立一个Message

Queue

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 52: Android应用开发 - 沈大海

Activity的四个状态

1 ActiveRuning 一个新 Activity 启动入栈后它在屏幕最前端处于栈的最顶端此时它处于可见并可和用户交互的激活状态2 Paused 当 Activity 被另一个透明或者 Dialog 样式的Activity 覆盖时的状态此时它依然与窗口管理器保持连接系统继续维护其内部状态所以它仍然可见但它已经失去了焦点故不可与用户交互3 Stoped 当 Activity 被另外一个 Activity

覆盖失去焦点并不可见时处于 Stoped状态4 Killed Activity 被系统杀死回收或者没有被启动时处于Killed状态

53

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 53: Android应用开发 - 沈大海

Activity 的各个回调函数与状态 之间的关系

l protected void onCreate(Bundle savedInstanceState) l protected void onStart() l protected void onResume() l protected void onPause() l protected void onStop() l protected void onDestroy()

54

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 54: Android应用开发 - 沈大海

bull在 Android中 应用的响应性被bull活动管理器 (Activity Manager)和bull窗口管理器 (Window Managerndash(这两个系统服务所监视 ndash当用户触发了输入事件 (如键盘输入 点击按钮等 ) ndash如果应用 5秒内没有响应用户的输入事件 那么 Android会认ndash为该应用无响应 便弹出 ANR(Application No Response)

ndash在正常情况下 Android程序会在一条单线程里运行 如果 Activity要处理一件比较耗时的工作 应ndash该交给子线程完成 否侧会因为主线程被阻塞 后面的用户输入事件因没能在 5秒内响应 导致应用出现

Android- 应用程序的响应性

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 55: Android应用开发 - 沈大海

Intent56

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 56: Android应用开发 - 沈大海

57

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 57: Android应用开发 - 沈大海

58

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 58: Android应用开发 - 沈大海

59

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 59: Android应用开发 - 沈大海

60

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 60: Android应用开发 - 沈大海

Intent 跟 pendingIntent 间的联系

bull intent 执行后的操作常和 alermanger 和notificationmanager 一起使用 Intent 一般是用作Activity Sercvice BroadcastReceiver之间传递数据而 Pendingintent 一般用在 Notification上可以理解为延迟执行的intent

bull PendingIntent 是对 Intent 一个包装

61

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 61: Android应用开发 - 沈大海

BroadcastReceiver简介lBroadcastReceiver的作用每个 Broadcast Receiver都可以接收一种或若干种 Intent作为触发事件

lBroadcastReceiver不执行任何任务仅仅是接受并响应广播通知的一类组件

lBroadcastReceiver 不包含任何用户界面

62

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 62: Android应用开发 - 沈大海

Service 简 介

是什么Service在 Android中是一种长生命周期的组件它不实现任何用户界面用来做什么实现不需要用户界面但是需要一直运行的功能如音乐播放器怎么用实现一个自己的 service启动执行 contextstartService()contextbindService()

63

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 63: Android应用开发 - 沈大海

Service 的生命周期

64

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 64: Android应用开发 - 沈大海

Android-与服务进行进程间通信客户端和服务通过 IBinder对象联系在一起 bindService() 方法调用时 需要 IntentServiceConnection和 flag参数 其中 serviceConnection对象用于接收服务 onBind() 方

法返回的 IBinder对象 并且该对象会传入到第二个参数 serviceConnetion对应的方法中 触发

方法的回调 总而言之 使得客户端持有到达 service对象的引用

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 65: Android应用开发 - 沈大海

Android-AIDL 实现进程间通信对于客户端和服务之间通信 虽然可以通过 IBinder 实现 但需要共享业务实现 如果在进程间通信的话 需要使用 AIDL(Android Interface Definition Language) 进行

AIDL 是一种接口定义语言 用于约束两个进程间的通讯规则 供编译器生成代码 实现 Android设备上的两个进程间通信 (IPC)AIDL的 IPC 机制和 EJB 所采用的 CORBA很类似 进程之间的通信信息 首先会被转换成 AIDL协议消息 然后发送给对方 对方收到 AIDL协议消息后再转换成相应的对象 由于进程之间的通信信息需要双向转换 所以 android采用代理类在背后实现了信息的双向转换 代理类由 android 编译器生成 对开发人员来说是透明的

使用方式如下 1 定义 AIDL(同接口相似 但没有可见性 扩展名有 java--gt aidl)IDownloadServiceaidl 注意扩展名package cnshenaidlinterface IDownloadService

void download(inoutinout String path)in|out|inout 是参数的方向 ide 会自动在 gen 包下生成对应的 java类 接口文件中生成一个 Stub 的抽象类 里面包括 aidl 定

义的方法 还包括一些其它辅助方法 值得关注的是 asInterface(IBinder iBinder)它返回接口类型的实例 对于远程服务调用 远程服务返回给客户端的对象为代理对象 客户端

onServiceConnected(ComponentName name IBinder service) 方法引用该对象时不能直接强转成接口类型的实例 而应该使用 asInterface(IBinder iBinder) 进行类型转换

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 66: Android应用开发 - 沈大海

Android-AIDL 实现进程间通信编写 AIDL 需要注意 1 接口名和 aidl 文件名相同 2 接口和方法前不用加访问权限修饰符 publicprivateprotected等 也不能用 finalstatic3Aidl默认支持的类型包话 java 基本类型 (intlongboolean等 )和 (StringListMap CharSequence) 使用这些类型时不需要 import声明 对于 List和 Map 中的元素类型必须是 Aidl支持的类型 如果使用自定义类型作为参数或返回值 自定义类型必须实现 Parcelable 接 口 4自定义类型和 AIDL生成的其它接口类型在 aidl描述文件中 应该显式 import即便在该类

和定义的包在同一个包中 5在 aidl 文件中所有非 Java 基本类型参数必须加上 in out inout 标记 以指明参数是

输入参数输出参数还是输入输出参数 6Java原始类型默认的标记为 in 不能为其它标记

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 67: Android应用开发 - 沈大海

Android-AIDL 实现进程间通信javabean 必须实现 Parcelable 接口class Person implements Parcelable

idnamegetsetpublic int describeContents()

return 0把 javanbean 中的数据写到 Parcelpublic void writeToParcel(Parcel dest int flags) destwriteInt(thisid)

destwriteString(thisname)添加一个静态成员 名为 CREATOR该对象实现了 ParcelableCreator 接口public static final ParcelableCreatorltPersongt CREATOR = new ParcelableCreatorltPersongt()

public Person createFromParcel(Parcel source) return new Person(sourcereadInt() sourcereadString())public Person[] newArray(int size) return new Person[size]

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 68: Android应用开发 - 沈大海

Android-AIDL 实现进程间通信在自定义类型包中定义 aidl 声明文件Personaidl注意 parcelable 是小写package cnshendomainparcelable Person

接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 )PersonServiceaidlpackage cnshenaidlimport cnshendomainPersoninterface IPersonService void save(in Person person)

创建 aidl 接口实现类 ( 通过继承 $ 业务接口 stub 类实现 )public class ServiceBinder extends IPersonServiceStub

public void save(Person person) throws RemoteException Logi(PersonService persongetId()+=+ persongetName())

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 69: Android应用开发 - 沈大海

Android-AIDL 实现进程间通信实现 service的 onBind 方法 返回值就是上一步创建的 aidl 实现类对象 public IBinder onBind(Intent intent)

return new ServiceBinder()

客户端通过隐式意图访问服务 ltservice androidname=PersonServicegt

ltintent-filtergtltaction androidname=cnshenprocessaidlPersonService gt

new Intent(cnshenprocessaidlPersonService)

复制 aidl 文件和所在包到客户端对应的 src下 ( 客户端会自动生成对应 java类 )thisbindService(thisscBIND_AUTO_CREATE)sc = new ServiceConnection()

public void onServiceConnected(ComponentNameIBinder service) personService = IPersonServiceStubasInterface(service)personServicesave(new Person(56liming))

public void onServiceDisconnected(ComponentName name)

personService = null

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 70: Android应用开发 - 沈大海

IPC 框架分析 bull Android 的设计 Activity托管在不同的的进

程 Service也都是托管在不同的进程不同进程间的 ActivityService 之间要交换数据属于 IPC

bull Binder就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架

bull Binder 是一个很低层的概念上面一层根本都看不到 Binder 而是 Activity跟一个 Service 的对象直接通过方法调用获取服务

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 71: Android应用开发 - 沈大海

IPC-对象请求代理架构bull 在 Android 中要完成某个操作所需要做

的就是请求某个有能力的服务对象去完成动作而无需知道这个通讯是怎样工作的以及服务在哪里

bull Andoid的 IPC 在本质上属于对象请求代理架构 Android 的设计者用 CORBA 的概念将自己包装了一下实现了一个微型的轻量级 CORBA 架构

bull 只是解决本机的进程间的通讯

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 72: Android应用开发 - 沈大海

Android 的对象代理结构

Service Manager

提供了

add service

check service

两个重要的方法并且维护了一个服务列表记录登记的服务名称和句柄

这样 client 应用能够找到所需要的 service

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 73: Android应用开发 - 沈大海

Binder architecture Binder java Binder c++

Java binder framework

Native binderframework

Binder core systemBBinder-gtIBinderlt-BpBinder

Binder AdapterIPCThreadeStateProcessState

Binder linux driver

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 74: Android应用开发 - 沈大海

Binder 核心类bull IBinder

ndash 虚拟类bull BBinder

ndash BBinder有 onTransact消息处理函数 bull BpBinder

ndash BpBinder 有消息传递函数 transcat

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 75: Android应用开发 - 沈大海

Service 闭合循环框架

bull Android 设计中 Native Service和 Android Service 采用了同一个闭合循环框架这个闭合循环框架放置在 Native的 C++ 空间中 ProcessStateProcessStatecpp 和 IPCThreadStateIPCThreadStatecpp

两个类完成了全部工作 bull 关于 ProcessState和 IPCThreadState在系统开发课程介绍

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 76: Android应用开发 - 沈大海

Android 启动过程bull (1) init 进程启动bull (2) Native 服务启动bull (3) System Server Android 服务启动bull (4) Home 启动

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 77: Android应用开发 - 沈大海

bull 文件操作bull Preferences10556401055640bull SQLite 库存储bull 网络

bull content provider

Android 中的数据保存78

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 78: Android应用开发 - 沈大海

文件操作

bull openFileInputbull openFileOutput

bull 读取资源文件bull getResource()openRawResource(Rrawxxx)

79

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 79: Android应用开发 - 沈大海

Preferences

bull 轻量级的bull 保存的是原始数据类型bull 常用于保存程序配置信息

SharedPreferences settings = getSharedPreferences(SETTING_INFOS 0)String name = settingsgetString(NAME )String password = settingsgetString(PASSWORD )

80

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 80: Android应用开发 - 沈大海

bull 过 ContextgetSharedPreferences()得到一个bull SharedPreferences bull 获取一个 Editor 对保存的参数进行编辑bull commit() 进行提交bull SharedPreferences settings = getSharedPreferences(ldquoinfordquo 0)bull Editor editor = settingsedit()bull editorputString(ldquonamerdquo nameEditTextgetText()toString())bull putString(ldquopwdrdquo passwordEditTextgetText()toString())bull commit()

81

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 81: Android应用开发 - 沈大海

Android- 使用嵌入式 SQLite

Android 平台上集成的一个嵌入式关系型数据库 SQLite3支持 NULLINTEGERREAL (浮点数字) TEXT(字符串文本 ) 和 BLOB(二进制对象 ) 数据类型 虽然它支持的类型只有五种 但实际上 sqlite3也接受 varchar(n)char(n)decimal(ps) 等数据类型 只不过在运算或保存时会转成对应的五种数据类型

SQLite最大的特点是你可以把各种类型的数据保存到任何字段中 而不用关心字段声明的数据类型是什么 但定义为 INTEGER PRIMARY KEY 的字段只能存储 64 位整数 当向这种字段保存除整数以外

的数据时 将会产生错误 另外 SQLite 在解析 CREATE TABLE 语句时 会忽略字段名后面的数据类型信息

SQLite 可以解析大部分标准 SQL 语句 如 查询语句 select from where group by having

order by 排序子句SQLite 分页同 mysql 相同 limit 5 offset 3 | limit 35

82

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 82: Android应用开发 - 沈大海

Android- 使用嵌入式 SQLite

首次使用数据库需要创建表及初始化一些信息 升级时需要修改表信 android 提供了抽象类 SQLiteOpenHelper 完成此类功能

onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 onUpgrade(SQLiteDatabase db int oldVersion int

ewVersion) 方法检测版本发生变化时更新库 getWritableDatabase()和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例

getWritableDatabase() 方法以读写方式打开数据库 一旦数据库的磁盘空间满了 数据库就只能读而不能写 倘若使用getWritableDatabase() 打开数据库就会出错 getReadableDatabase() 方法先以读写方式打开数据库 如果数据库的磁盘空间满了 就会打开失败 当打开失败后会继续尝试以只读方式打开数据库

83

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 83: Android应用开发 - 沈大海

Android-单元测试ltapplication androidicon=drawableicon package=gt ltuses-library androidname=androidtestrunner gt ltapplicationgtltinstrumentation androidname=androidtestInstrumentationTestRunner

androidtargetPackage=cnshenaction androidlabel=Tests for My App gt

public class XMLTest extends AndroidTestCase public void testSomething() throws Throwable

Logi(Test this is test 日志 )Systemoutprintln(ddd)AssertassertTrue(1 + 1 == 3)

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 84: Android应用开发 - 沈大海

Android-SQLite3 工具使用

ltTableLayout xmlnsandroid=httpschemasandroidcomapkresandroid

androidlayout_width=fill_parent androidlayout_height=wrap_content androidstretchColumns=0123 androidid=+idtlListgtltTableLayoutgt

85

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 85: Android应用开发 - 沈大海

ContentProvider简介lContentProvider是 Android提供的一种标准的共享数据的机制 l应用程序可以通过 content provider访问其它应用程序的一些私有数据lContentProvider的优点屏蔽了内部数据的存储细节向外提供l了上述统一的接口模型

86

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 86: Android应用开发 - 沈大海

Android- 使用 ContentProvider

使用内容供应商共享数据 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ) 需要很多

底层的交互细节 但是用该种方式 只使用 url即可对应用程序进行访问 并统一了数据访问方式 public class PersonContentProvider extends

ContentProviderpublic boolean onCreate()public Uri insert(Uri uri ContentValues values)

ltapplication androidicon=drawableicon

androidlabel=stringapp_namegtlt-- 注册供应商 --gtltprovider androidname=PersonContentProvider

androidauthorities=cnlgproviderspersonprovidergtltapplicationgt

87

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 87: Android应用开发 - 沈大海

Android- 使用 ContentProvider

88

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 88: Android应用开发 - 沈大海

Android-活动墙纸活动墙纸是 android21新增的特性 活动墙纸实质上是一个包含有 WallpaperService的 android应用 该服务必须含有一个 WallpaperServiceEngine该 Engine 是用户 surface 和系统之间的桥梁 他拥有绘制墙纸的 surface

首要的是 WallpaperService 必须携带内部 Engine 类进行创建 而且需要使用androidservicewallpaperWallpaperService 意图声明在清单文件中 以备设备识别为活动墙纸 需要关联 androidpermissionBIND_WALLPAPER权限到活动墙纸给 android 主程序

ltserviceandroidname=LiveWallpaperServiceandroidenabled=trueandroidicon=drawableiconandroidlabel=stringapp_nameandroidpermission=androidpermissionBIND_WALLPAPERgtltintent-filter androidpriority=1 gtltaction androidname=androidservicewallpaperWallpaperService gtltintent-filtergtltmeta-dataandroidname=androidservicewallpaperandroidresource=xmlwallpaper gt

ltservicegt

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 89: Android应用开发 - 沈大海

Android-活动墙纸墙纸描述文件

添加文件 resxmlwallpaperxml描述活动墙纸 ltmeta-data androidname=androidservicewallpaper

androidresource=xmlwallpaper gt

ltxml version=10 encoding=UTF-8gtltwallpaper xmlnsandroid=httpschemasandroidcomapkresandroid

androidthumbnail=drawablethumbnailandroiddescription=stringdescriptionandroidsettingsActivity=PreferenceActivitygt

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 90: Android应用开发 - 沈大海

Android-活动墙纸创建墙纸服务类public class LiveWallpaperService extends WallpaperService

public Engine onCreateEngine() return new SampleEngine()

public class SampleEngine extends Engine public void onCreate(SurfaceHolder surfaceHolder)public void onVisibilityChanged(boolean visible)public void onSurfaceChanged()public void onSurfaceCreated(SurfaceHolder holder)

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 91: Android应用开发 - 沈大海

Widgetbull ltreceiver androidname=MeWidgetProvider

androidicon=drawableboot_robotandroidlabel=AppWidget Lifegt

bull ltintent-filtergtbull ltaction

androidname=androidappwidgetactionAPPWIDGET_UPDATEgtbull ltactiongtbull ltcategory

androidname=androidintentcategoryDEFAULTgtltcategorygtbull ltintent-filtergtbull ltmeta-data androidresource=xmlapp_widget_infobull androidname=androidappwidgetprovidergtbull ltmeta-datagtbull ltreceivergt

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 92: Android应用开发 - 沈大海

获取手机所有连接管理对象bull public static boolean checkNet(Context context)

bull 获取手机所有连接管理对象(包括对 wi-finet 等连接的管理) bull try

bull ConnectivityManager connectivity = (ConnectivityManager) context

bull getSystemService(ContextCONNECTIVITY_SERVICE)

bull if (connectivity = null)

bull 获取网络连接管理的对象 bull NetworkInfo info = connectivitygetActiveNetworkInfo()

bull if (info = nullampamp infoisConnected())

bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED)

bull return true

bull

bull catch (Exception e)

bull

bull return false

bull

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 93: Android应用开发 - 沈大海

检查网络状态变化bull ltreceiver androidname=itcastutilNetCheckgt bull ltintent-filtergt bull ltaction androidname=androidnetconnCONNECTIVITY_CHANGEgt bull ltintent-filtergt bull ltreceivergtbull public class NetUtil extends BroadcastReceiverbull public void onReceive( Context context Intent intent ) bull bull ConnectivityManager connectivityManager = (ConnectivityManager)

contextgetSystemService( ContextCONNECTIVITY_SERVICE ) bull NetworkInfo info = connectivityManagergetActiveNetworkInfo() bull if (info = nullampamp infoisConnected()) bull 判断当前网络是否已经连接 bull if (infogetState() == NetworkInfoStateCONNECTED) bull ToastmakeText( context ok ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull elsebull bull ToastmakeText( context err ToastLENGTH_SHORT )show() bull bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongtbull ltuses-permission androidname=androidpermissionACCESS_NETWORK_STATEgt

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 94: Android应用开发 - 沈大海

AsyncTaskbull 匿名线程的方式是存在缺陷的bull 第一线程的开销较大如果每个任务都要创建一个线程那么应用

程序的效率要低很多bull 第二线程无法管理匿名线程创建并启动后就不受程序的控制了

如果有很多个请求发送那么就会启动非常多的线程系统将不堪重负另外前面已经看到在新线程中更新 UI还必须要引入 handler 这让代码看上去非常臃肿

bull bull 为了解决这一问题 Android在 15版本引入了 AsyncTask bull AsyncTask 的特点是任务在主线程之外运行而回调方法是在主线程

中执行这就有效地避免了使用 Handler带来的麻烦阅读AsyncTask 的源码可知 AsyncTask 是使用 javautilconcurrent 框架来管理线程以及任务的执行的 concurrent 框架是一个非常成熟高效的框架经过了严格的测试这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 95: Android应用开发 - 沈大海

AsyncTask 是抽象类bull doInBackground(Params p) 在此方法中实现任务的执行工作比如连接网络获取数据等通常还应该实现

bull onPostExecute(Result r) 方法因为应用程序关心的结果在此方法中返回需要注意的是AsyncTask 一定要在主线程中创建实例

ndash AsyncTask 定义了三种泛型类型 Params Progress和 Result

bull Params 启动任务执行的输入参数比如 HTTP请求的 URL

bull Progress 后台任务执行的百分比 bull Result 后台执行任务最终返回的结果比如 String

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 96: Android应用开发 - 沈大海

ndash onPreExecute() bull 当任务执行之前开始调用此方法可以在这里显示进度对话框

ndash doInBackground(Params)bull 此方法在后台线程执行完成任务的主要工作通常需要较长的时间在执行过程中可以调用publicProgress(Progress) 来更新任务的进度

ndash onProgressUpdate(Progress)bull 此方法在主线程执行用于显示任务执行的进度

ndash onPostExecute(Result) bull 此方法在主线程执行任务执行的结果作为此方法的参数返回

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 97: Android应用开发 - 沈大海

Android-互联网 ( 多线程下载 )

1 多线程下载取得下载文件大小 并构建随机访问文件HttpURLConnectiongetContentLength()RandomAccessFile file = new RandomAccessFile(QQWubiSetupexerwd)filesetLength(filesize)设置本地文件的长度设置每个线程连接的请求属性 range为指定范围HttpURLConnectionsetRequestProperty(Range bytes=2097152-4194303) 定位文件位置写入信息 fileseek(2097152)filewrite()

注 多线程下载时 不要判断 200值 style=androidstyleWidgetProgressBarHorizontalltstyle name=WidgetProgressBarHorizontalgt ltitem name=androidindeterminateDrawablegt

androiddrawableprogress_indeterminate_horizontalltitemgt ltitem name=androidminHeightgt20dipltitemgt ltitem name=androidmaxHeightgt20dipltitemgtltstylegt动态添加进度条时 指定的是 androidRattrprogressBarStyleHorizontal样式值

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 98: Android应用开发 - 沈大海

ListView 优化bull public class WeiboStatuAdapter extends BaseAdapter

bull public Context con

bull public ListltStatusgt alls

bull public LayoutInflater lif

bull public WeiboStatuAdapter(Context conListltStatusgt as)

bull thiscon=con

bull lif=LayoutInflaterfrom(con)

bull thisalls=as

bull

bull public int getCount() return allssize()+2

bull public Object getItem(int arg0) return null

bull public long getItemId(int index)

bull if(index==0) 选中第一项bull return 0

bull else if(indexgt0ampamp(indexltthisgetCount()-1))

bull return allsget(index-1)getId() 如果用户选中了中间项 bull else

bull return -1 表示用户选中最后一项bull

bull 增加更多的数据bull public void addMoreData(ListltStatusgt moreStatus)

bull thisallsaddAll(moreStatus) 把新数据增加到原有集合bull thisnotifyDataSetChanged()

bull

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 99: Android应用开发 - 沈大海

Android- 多媒体 (照相机 )

thisrequestWindowFeature(WindowFEATURE_NO_TITLE)无标题Window w = thisgetWindow()wsetFlags(WindowManagerLayoutParamsFLAG_FULLSCREEN

WindowManagerLayoutParamsFLAG_FULLSCREEN)设置全屏waddFlags(WindowManagerLayoutParamsFLAG_KEEP_SCREEN_ON) 高亮

surfaceViewgetHolder()setFixedSize(176 144)设置分辨率surfaceViewgetHolder()setType(SurfaceHolderSURFACE_TYPE_PUSH_BUFFERS)surfaceViewgetHolder()addCallback()回调

WindowManager wm = getSystemService(ContextWINDOW_SERVICE)窗口管理器Display display = wmgetDefaultDisplay()Camera camera = Cameraopen() 打开照相机CameraParameters parameters = cameragetParameters()parameterssetPreviewSize(displaygetWidth()displaygetHeight()) 大小parameterssetPreviewFrameRate(3)每秒 3帧parameterssetPictureFormat(PixelFormatJPEG)设置照片的输出格式parametersset(jpeg-quality 85)照片质量parameterssetPictureSize(displaygetWidth()displaygetHeight())camerasetParameters(parameters)

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 100: Android应用开发 - 沈大海

Android- 多媒体 (照相机 )

通过 SurfaceView显示取景画面camerasetPreviewDisplay(surfaceViewgetHolder())camerastartPreview() 开始预览cameraautoFocus(null)自动对焦cameratakePicture(null null null jpegCallback)拍照片camerastopPreview()停止预览camerarelease()释放摄像头

onKeyDownpublic boolean onKeyDown(int keyCode KeyEvent event)

if(camera = null ampamp eventgetRepeatCount() == 0)case KeyEventKEYCODE_SEARCH

PictureCallbackBitmap bmp = BitmapFactorydecodeByteArray(data 0 datalength)File jpg = new File(EnvironmentgetExternalStorageDirectory()1jpg)FileOutputStream fos = new FileOutputStream(jpg)bmpcompress(BitmapCompressFormatJPEG 100fos)fosclose()camerastartPreview()

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 101: Android应用开发 - 沈大海

Android- 多媒体 (照相机 )

使用意图模拟拍照若没有摄像头硬件 可使用系统内置的 provider 实现摄像头功能 (该功能 22 的模拟器不支持 )

Intent intent = new Intent(androidproviderMediaStoreACTION_IMAGE_CAPTURE) 指定输出文件outputFileUri指定照片存放的地址 若有的话存放全尺寸大照片 否则返回位图 在 onActivityResult 方法中接收intentputExtra(MediaStoreEXTRA_OUTPUT outputFileUri)startActivityForResult(intent 0)

BitmapFactoryOptions options = new BitmapFactoryOptions()optionsinSampleSize = 1Bitmap bitmap = BitmapFactorydecodeFile(_path options)_imagesetImageBitmap(bitmap)lt-- 需要使用如下权限 --gtltuses-permission androidname=androidpermissionCAMERA gt ltuses-feature androidname=androidhardwarecamera gt ltuses-feature androidname=androidhardwarecameraautofocus gt

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 102: Android应用开发 - 沈大海

bull Button btaddPic=(Button)thisfindViewById(RidbtGallery)bull btaddPicsetOnClickListener(new OnClickListener()bull bull Overridebull public void onClick(View v) bull Intent i = new

Intent(androidmediaactionIMAGE_CAPTURE)bull startActivityForResult(i ActivityDEFAULT_KEYS_DIALER)bull bull bull )

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 103: Android应用开发 - 沈大海

bull protected void onActivityResult(int requestCode int resultCode Intent data)

bull TODO Auto-generated method stubbull superonActivityResult(requestCode resultCode data)bull Bundle extras = datagetExtras()bull Bitmap b = (Bitmap) extrasget(data)bull ByteArrayOutputStream baos = new ByteArrayOutputStream()bull bcompress(BitmapCompressFormatJPEG 100 baos)bull dat = baostoByteArray()bull thishasPic=true

bull

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 104: Android应用开发 - 沈大海

地图开发bull Google 地图

ndash Google MAPndash 位置导航

bull 第三方地图ndash 高德

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 105: Android应用开发 - 沈大海

bull 1获取指纹bull CDocuments and SettingsAdministratorgtcd C

Documents and SettingsAdministratbull orandroid

bull CDocuments and SettingsAdministratorandroidgtkeytool -list -keystore debugkEystore

bull 默认密码 androidbull 2申请 apikeybull httpcodegooglecomintlzh-CNandroidmaps-api-si

gnuphtml

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 106: Android应用开发 - 沈大海

使用 Google 地图bull MapActivity

bull 任何显示 MapView的 Activity都要继承这个类bull 内部封装了访问网络的方法

bull MapView

bull MapControllerbull 控制地图的 移动和缩放

bull Overlay

bull GeoPoint

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 107: Android应用开发 - 沈大海

bull ltuses-library androidname=ldquocomgoogleandroidmapsrdquogt

bull ltuses-permission androidname=androidpermissionINTERNETgtltuses-permissiongt

bull MapView map=new MapView(thisrdquokeyrdquo)

bull MapsetTraffic 地图模式bull Map setSatellite卫星模式bull MapsetStreetView街景模式

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 108: Android应用开发 - 沈大海

bull MapControl=mMapviewgetController()

bull geoPoint=new 成都GeoPoint((int)30659251000000 (int)1040657621000000)

bull mMapControlleranimateTo(geoPoint)

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 109: Android应用开发 - 沈大海

bull Public class myLocationOverLay extends OverLay

bull

bull public boolean draw(Canvas cmapView mboolean shadwlong when)

bull

bull

bull

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 110: Android应用开发 - 沈大海

定位系统bull LocationManager

bull getSystemService(ConextLOCATION_SERVICE)bull 注册周期更新视图的侦听bull LmrequestLocationUpdates(LocationmanagerGPS_PROVI

DER10000LocationListener)

bull LocationProviderbull LocationListener

bull onLocationChangedbull onProviderDisabledbull onproviderEnabledbull onStatusChanged

bull Criteriabull GeoCoder

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 111: Android应用开发 - 沈大海

bull ( 1 ) public void setAccuracy( int accuracy ) bull 位置解析的精度高或低参数 Criteria ACCURACY_FINE 精确模式 Criteria ACCURACY_COARSE 模糊模式

bull ( 2 ) public void setAltitudeRequired(boolean altitudeRequired ) bull 是否提供海拔高度信息是或否 bull ( 3 ) public void setBearingRequired( boolean bearingRequired ) bull 是否提供方向信息是或否 bull ( 4 ) public void setCostAllowed( boolean costAllowed ) bull 是否允许运营商计费是或否bull ( 5 ) public void setPowerRequirement( int level ) bull 电池消耗无低中高参数 Criteria NO_REQUIREMENT

Criteria POWER_LOW Criteria POWER_MEDIUM or Criteria POWER_HIGH

bull ( 6 ) public void setSpeedRequired( boolean speedRequired )

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 112: Android应用开发 - 沈大海

bull criteriasetAccuracy(ACCURACY_FINE)

bull ACCURACY_FINE

bull 精确度设置为模糊解决所有手机无法启动CriteriaACCURACY_COARSE

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 113: Android应用开发 - 沈大海

Android Ndk 开发bull JNI 实现 NDK 定义的 native 方法调用bull 1 编写 Java 类定义 native 方法bull 2 通过 javah命令生成类的 h 文件bull 3创建 c 的项目工程bull 4 编写 c 的函数实现bull 5 编译生成 sobull 6拷贝 so到 java项目中bull 7在 staticbull SystemloadLaibrary(xxxx)bull bull 8直接调用 native 方法

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 114: Android应用开发 - 沈大海

应用程序的优化bull 代码优化的关键

o 少用浮点运算文件 pipe 数据库访问o 用高效的方式 StringBuffer 代替大量临时 String o SoundPool 代替多个 MediaPlayer o texture 代替 canvas o Logd() 代替 Systemoutprint() o 避免 invalidate()o 重视 onMeasureonLayoutonDrawonTouchEventgetView 等函

数的效率bull 游戏开发

o 少用 new()enumIteratorHashMapArrayssort()ClassgetXXX()hellip

o 多用 private final 局部变量o 2D 善用 draw_texture 3D 善用 VBO 顶点缓冲o 触屏事件时暂停接受运动感应事件o 用 NDK 实现关键代码

bull 不要求速度时可用 WebView 和网页实现界面bull 编译时执行代码优化

bull 谢谢

Page 115: Android应用开发 - 沈大海

bull 谢谢