Android应用开发 - 沈大海
Upcoming SlideShare
Loading in...5
×
 

Android应用开发 - 沈大海

on

  • 1,739 views

Android应用开发 - 沈大海

Android应用开发 - 沈大海

Statistics

Views

Total Views
1,739
Views on SlideShare
1,546
Embed Views
193

Actions

Likes
2
Downloads
54
Comments
0

2 Embeds 193

http://blog.lamper.cn 192
http://reader.youdao.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • 1)         Java 层 a)         类 Resources Ophone 为访问不同类型的资源提供了不同的接口,这些接口被封装在类 Resources 中。例如访问字符串的接口 getString() ,访问 drawable 类型的接口 getDrawable() 等等。该类管理着另外两个重要的类 Configuration 和 AssetManager 。 b)         类 Configuration 类 Configuration 保存了当前系统中的配置,例如字体,语言等等信息。 c)         类 AssetManager 类 AssetManager 提供了以数据流方式访问应用程序资源的方法。它通过 native 的方法来实现访问资源。 AssetManager 管理的资源有两个来源:一个是应用程序的资源,通过访问应用程序的 apk 文件得到;另一个是系统的资源,通过访问包含系统资源的 apk 文件获得。 2)         Native 层 Native 层负责管理相应的 apk 文件,如上面所述,有两个文件,一个是系统的 apk 文件,另一个是应用程序自身的 apk 文件。 Native 层会把资源组织成一个资源表( Resource Table )用来提高访问资源的速度。
  • 启动 Frame 动画的代码 animationDrawable.start(); 不能应用在 OnCreate() 方法中,因为在 OnCreate() 中 AnimationDrawable 还没有完全的与 ImageView 绑定。在 OnCreate() 中启动动画,只能看到第一张图片。这里在触摸事件中实现的。
  • 最快 : SensorManager.SENSOR_DELAY_FASTEST 最低延迟,一般不是特别敏感的处理不推荐使用,该种模式可能造成手机电力大量消耗,由于传递的为原始数据,算法不处理好将会影响游戏逻辑和 UI 的性能。 游戏: SensorManager.SENSOR_DELAY_GAME 游戏延迟,一般绝大多数的实时性较高的游戏都使用该级别。 普通 :SensorManager.SENSOR_DELAY_NORMAL 标准延迟 : 对于一般的益智类或 EASY 级别的游戏可以使用 , 但过低的采样率可能对一些赛车类游戏有跳帧现象 . 用户界面 :SensorManager.SENSOR_DELAY_UI 一般对于屏幕方向自动旋转使用 , 相对节省电能和逻辑处理 , 一般游戏开发中我们不使用 .
  • /*x 该值表示方位, 0 代表北( North ); 90 代表东( East ); 180 代表南( South ); 270 代表西( West ) 如果 x 值正好是这 4 个值之一,并且手机是水平放置,手机的顶部对准的方向就是该值代表的方向。 y 值表示倾斜度,或手机翘起的程度。当手机绕着 X 轴倾斜时该值发生变化。 y 值的取值范围是 -180≤y 值 ≤ 180 。 假设将手机屏幕朝上水平放在桌子上,这时如果桌子是完全水平的, y 值应该是 0 (由于很少有桌子是绝对水平的, 因此,该值很可能不为 0 ,但一般都是 -5 和 5 之间的某个值)。这时从手机顶部开始抬起,直到将手机沿 X 轴旋转 180 度(屏幕向下水平放在桌面上)。 在这个旋转过程中, y 值会在 0 到 -180 之间变化,也就是说,从手机顶部抬起时, y 的值会逐渐变小, 直到等于 -180 。如果从手机底部开始抬起,直到将手机沿 X 轴旋转 180 度,这时 y 值会在 0 到 180 之间变化。 也就是 y 值会逐渐增大,直到等于 180 。可以利用 y 值和 z 值来测量桌子等物体的倾斜度。 z 值表示手机沿着 Y 轴的滚动角度。表示手机沿着 Y 轴的滚动角度。取值范围是 -90≤z 值≤ 90 。 假设将手机屏幕朝上水平放在桌面上,这时如果桌面是平的, z 值应为 0 。将手机左侧逐渐抬起时, z 值逐渐变小,直到手机垂直于桌面放置,这时 z 值是 -90 。将手机右侧逐渐抬起时, z 值逐渐增大, 直到手机垂直于桌面放置,这时 z 值是 90 。在垂直位置时继续向右或向左滚动, z 值会继续在 -90 至 90 之间变化。 */
  • <!-- Component name of an activity that allows the user to modify the current settings for this wallpaper. --> <!-- Reference to a the wallpaper's thumbnail bitmap. --> <!-- Name of the author of this component, e.g. Google. --> <!-- Short description of the component's purpose or behavior. -->
  • package cn.shen.wallpaper.service; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Handler; import android.service.wallpaper.WallpaperService; import android.view.MotionEvent; import android.view.SurfaceHolder; /* * This animated wallpaper draws a rotating wireframe cube. */ public class LiveWallpaperService extends WallpaperService { private final Handler handler = new Handler(); /** * 创建引擎 */ public Engine onCreateEngine() { return new CubeEngine(); } /** * 立方体引擎 */ class CubeEngine extends Engine { private final Paint mPaint = new Paint();// 画板 private float xOffset ;// 偏移量 private float touchX = -1;// x 触点 private float touchY = -1;// y 触点 private float centerX;// x 中心 private float centerY;// y 中心 private boolean visible;// 可见 private float step = 2; private float downX = -1; private float downY = -1; private float upX = -1; private float upY = -1; /** * 分线程运行程序 */ private Runnable r = new Runnable() { public void run() { doDraw(); } }; CubeEngine() { // Create a Paint to draw the lines for our cube // 初始化 Paint paint = mPaint;// 油漆 , 涂料 paint.setColor(0xffff0000);// 颜色 paint.setAntiAlias( true );// 抗锯齿 paint.setStrokeWidth(2);// 笔画宽度 paint.setStrokeCap(Paint.Cap. ROUND );// 帽形 paint.setStyle(Paint.Style. STROKE );// 样式 } // 启用触碰事件 public void onCreate(SurfaceHolder surfaceHolder) { super .onCreate(surfaceHolder); setTouchEventsEnabled( true ); } // public void onDestroy() { super .onDestroy(); handler.removeCallbacks(r);// 删除队列中所有该回调消息 } // 可见性发生变化 public void onVisibilityChanged( boolean visible) { this .visible = visible; if (visible) { doDraw();// 画框 } else { // 删除消息中的队列 handler.removeCallbacks(r); } } // 表面变化时 public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super .onSurfaceChanged(holder, format, width, height); // store the center of the surface, so we can draw the cube in the // right spot centerX = width / 2.0f;// 计算中心位置 ( 表面包容器宽度的一半 ) centerY = height / 2.0f;// 计算中心位置 ( 表面包容器高度的一半 ) doDraw(); } // 表面销毁时 public void onSurfaceDestroyed(SurfaceHolder holder) { super .onSurfaceDestroyed(holder); this .visible = false ; handler.removeCallbacks(r); } // 响应偏移量发生改变时事件 WallpaperManager.setWallpaperOffsets(). public void onOffsetsChanged( float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels) { this .xOffset = xOffset; doDraw();// 画框 } /* * Store the position of the touch event so we can use it for drawing * later */ // 响应触碰事件 public void onTouchEvent(MotionEvent event) { // if (event.getAction() == MotionEvent.ACTION_MOVE) { // this.touchX = event.getX();// 得到移动点 x 坐标 // this.touchY = event.getY();// 得到移动点 y 坐标 // } else { // this.touchX = -1; // this.touchY = -1; // } if (event.getAction() == MotionEvent. ACTION_DOWN ) { this .downX = event.getX(); this .downY = event.getY(); } else { this .upX = event.getX(); this .upY = event.getY(); } super .onTouchEvent(event); } /* * Draw one frame of the animation. This method gets called repeatedly * by posting a delayed Runnable. You can do any drawing you want in * here. This example draws a wireframe cube. */ void doDraw() { final SurfaceHolder holder = getSurfaceHolder();// 得到表面包容器 Canvas c = null ; try { c = holder.lockCanvas();// 锁定画布 if (c != null ) { drawCube(c);// 画立方体 drawTouchPoint(c);// 画触点 } } finally { if (c != null ) holder.unlockCanvasAndPost(c);// 解锁画布并发送 } // Reschedule the next redraw handler.removeCallbacks(r);// 画完图形后 , 删除对立中消息 . if (visible) { handler.postDelayed(r, 1000 / 25);// 若墙纸可见 , 发送延迟消息 } } /* * Draw a wireframe cube by drawing 12 3 dimensional lines between * adjacent corners of the cube 绘制立方体 */ void drawCube(Canvas c) { if (step >= this .centerX) { step = 2; } float left = this .centerX - step; float top = this .centerY + step; float right = this .centerX + step; float bottom = this .centerY - step; c.save(); c.translate(0, 0);// 移动到中间位置 c.drawColor(0xff000000);// 用指定颜色填充画布的位图 c.drawLine(left, top, right, top, mPaint); c.drawLine(right, top, right, bottom, mPaint); c.drawLine(left, bottom, right, bottom, mPaint); c.drawLine(left, top, left, bottom, mPaint); c.restore(); step = step + 2; } /* * Draw a circle around the current touch point, if any. */ void drawTouchPoint(Canvas c) { if (downX > 0 && upX > 0 && (!(downX == upX && downY == upY))) { float originalX = (downX + upX) / 2 ; float originalY = (downY + upY) / 2 ; double radius = Math. sqrt (Math. pow (upX - downX,2) + Math. pow (upY - downY,2)) / 2 ; c.drawCircle(originalX, originalY, new Float(radius), mPaint); } } } }
  • false @android:drawable/progress_horizontal @android:drawable/progress_indeterminate_horizontal 20dip 20dip

Android应用开发 - 沈大海 Android应用开发 - 沈大海 Presentation Transcript

  • LAMP 人 主题分享交流会 www.LAMPER.cn QQ 群: 3330312 http://weibo.com/lampercn
  • Android 开发技术培训 沈大海
  • 知识大纲
    • Android 手机空间划分
    • Android Framework
    • Android SDK,NDK 开发环境搭建
    • Android Application 分析
    • Android Loop Handler 机制
    • Android 应用开发基本组件使用
    • 实现 AIDL 定义远程通讯 Service
    • 实现 Widget,Wallpaper
    • Google Map 开发
    • LocaltionManager
    • 使用 NDK 开发
    • 开源引擎 Cocos2d-x 介绍
    • 开发优化
  • Android 手机软硬件形态
  • Android Framework
  • Android 体系结构
    • 应用程序 (Applications) :依据 User 的期望而将 AF 的组件及 Libaraies 组件组合而成的高阶服务。
    • 应用框架 (Application Framework, 简称 AF) :这是结合 Applications 与 Libraries 的幕后主架构,让 Libraries 组件能不断地为 Applications 所重复使用 (Reuse) 。
        • 丰富而又可扩展的视图( Views )
        • 内容提供器( Content Providers )
        • 资源管理器( Resource Manager )
        • 通知管理器 ( Notification Manager )
        • 活动管理器( Activity Manager )
    • Libraries : Android 里已经提供的 C/C++ 库存组件 ( 或称模块 ) 。例如, SQLite 数据库系统、 OpenGL 3D 绘图系统等。
    • Android Runtime : Java 语言层级的 Virtual Machine 。
    • Linux 核心 : Android 依赖 Linux 2.6 来提供核心的服务,例如内存管理、进程 (Process) 管理、执行绪 (Thread) 管理等。
  • Android 层次 -kernel Android 基于 Linux 2.6 提供核心系统服务,例如:安全、内存管理、进程管理、网络堆栈、驱动模型。 Linux Kernel 也作为硬件和软件之间的抽象层,它隐藏具体硬件细节而为上层提供统一的服务。 使用 binder 作为进程间通讯机制,取代传统进程间通讯机制 Linux Kernel Display Driver Camera Driver Flash Driver SD Driver Keypad Driver Touch Driver USB Driver PM Common Kernel (File System, Networking, etc) ‏ Hardware Camera ISP Touch CPU MVED Driver GCU Driver MM Accelerate Battery Charging RTC Alarm Modem IPC Driver WIFI/BT Android Enhancement (Binder, Ash, Log, ADB, etc) ‏ Sensors Driver
  • Android – Hardware Abstraction Layer 用户空间的 C/C++ 库 遵循 Apache 协议 定义 Android 需要 linux driver 实现的接口 将 Android 彻底和硬件抽象出来
  • Android 层次结构 -Android Runtime Android 包含一个核心库的集合,提供大部分在 Java 编程语言核心类库中可用的功能。 Dalvik 虚拟机则是基于寄存器的,而非大多数 虚拟机所采用的基于栈的实现 Dalvik 虚拟机依赖于 Linux 内核提供基本功能, 如线程和底层内存管理。
  • Android 包含一个 C/C++ 库的集合,供 Android 系统的各个组件使用。这些功能通过 Android 的应用程序框架( application framework )暴露给开发者。下面列出一些核心库: 系统 C 库 多媒体库: OpenCore 界面管理 LibWebCore SGL 3D 库 FreeType SQLite Android 层次结构 -Libraries
  • Android 层次结构- Application Framework 通过提供开放的开发平台, Android 使开发者能够编制极其丰富和新颖的应用程序。开发者可以自由地利用设备硬件优势、访问位置信息、运行后台服务、设置闹钟、向状态栏添加通知等等,很多很多。 开发者可以完全使用核心应用程序所使用的框架 APIs 。应用程序的体系结构旨在简化组件的重用,任何应用程序都能发布他的功能且任何其他应用程序可以使用这些功能(需要服从框架执行的安全限制)。这一机制允许用户替换组件。 所有的应用程序其实是一组服务和系统,包括: View ActivityManager ContentProvider NotificationManager
  • Android 层次结构- Applications Android 魅力的终极体现: 对用户:良好的用户体验,强大的用户亲和力 对开发者:快速而灵活的开发平台,让开发者的灵感能快速转化为产品
  • Android 进程运行
  • 基本开发方向 -Android 移植、集成 所需知识 : Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库 Dalvik 虚拟机 Android GUI 系统 音频、视频和多媒体 电话部分的 连接部分 传感器部分 编译工具 Vim 或者 Emacs Android Shell 脚本 Android makefile Android python 使用 Android/build/tools
  • 基本开发方向 - 应用开发 所需知识 : Android 核心组件 Android UI 组件 Android GUI 编程 Android 事件处理 NDK 开发 OpenGL 开发 编译工具 Eclipse Java ,C 语言
  • 基本开发方向— Android 系统开发 所需知识 : Linux 操作系统知识 Linux 内核知识 Linux 驱动程序知识 Android 底层库 Dalvik 虚拟机 Android GUI 系统 音频、视频和多媒体 电话部分的 连接部分 传感器部分 编译工具 Vim 或者 Emacs Android Shell 脚本 Android makefile Android/build/tools Java 开发 JNI 技术
  • 三种开发形式
    • SDK 开发
      • Windows linux mac
    • NDK 开发
      • Windows linux
    • 源码开发
      • (完全源代码, Linux 中开发)
  • Android Applications
  • Android apk build and packaging
  • Android application unpackaging and run
  • AAPT 打包示意图
  • 限定符的类型和有效的值 限定符 有效值 语言 语言码,遵循 ISO 639-1 标准,小写,如 en, zh. 地区 遵循 ISO 3166-1-alpha-2 标准,大写,前面加小写的 “ r ” ,例如: rUS , rCN 屏幕朝向 port, land, square 屏幕像素密度 92dpi, 108dpi 等 触摸屏类型 notouch, stylus, finger 键盘是否可用 keysexposed, keyshidden 首选的输入法 nokeys, qwerty, 12key 首选非触摸导航方法 nonav, dpad, trackball, wheel 屏幕尺寸 320x240, 640x480 等,大尺寸必须在前
  • 资源管理框架
  • Activity 介绍
    • 展现为一个用户可视化界面
    • Activity 可以多种形式呈现,如全屏模式,对话框模式,透明模式等
    • Activity 的部分重要属性:
      • android:label="string resource"
      • android:icon="drawable resource"
      • android:launchMode=["multiple" | "singleTop" |"singleTask" | "singleInstance"]
  • 基础 UI
    • menu: 如何打造友好的菜单
    • ListView: 用好列表,做好程序
    • Dialog: 人机友好互动交流
    • Toast 和 Notification: 温馨的提醒
    • 各种 View 组件
    • 自定义 View 组件
  • Application ui description 通过绑定 Activity 的 setContentView() 方法,在 onResume 之后绘制
  • A tree-structure ui
  • View/windows base
  •  
  • 图形系统层次结构 Android Apps Application Framework Native Libraries HAL SurfaceFlinger Activity Manager Window Manager View System Display Driver(FrameBuffer..) View ---- Image, Shape, Text, Animation, Canvas...
  • 2D graphics process Activity android.view.* android.graphics.* (Canvas, Paint,Path, Picture,Region...) ActivityManager WindowManager frameworks/base/core/jni/android/graphic SurfaceFlinger HAL / FrameBuffer Get Surface Obj. /external/skia
  • 3D graphics process Activity android.opengl.* javax.microedition.khronos.egl javax.microedition.khronos.opengl (GLSurfaceView...) ActivityManager WindowManager frameworks/.../gles_jni/* SurfaceFlinger HAL / FrameBuffer Get Surface Obj. /frameworks/base/opengl
  • Android 图形系统
    • GUI include:
    • Java --- android.graphics (Skia lib, draw feature)
    • android.view.surface
    • android.view.view
    • javax.microedition.khronos.opengles
    • android.opengl
    • C/C++ --PixelFlinger (tool lib)
    • libui
    • SurfaceFlinger
    • Skia
    • Opengl/es 3D
  • Android 图形系统
  • Android- 动画
    • tween
    • 对 view 的内容进行一系列变换 ( 平移 , 缩放 , 渐变 ..)
    • frame
    • 顺序播放一组图片 , 达到动画的效果 .
    动画的类型 Xml 定义动画使用的配置节点 编码定义动画使用的类 渐变透明度动画效果 <alpha/> AlphaAnimation 渐变尺寸缩放动画效果 <scale/> ScaleAnimation 画面位置移动动画效果 <translate/> TranslateAnimation 画面 旋转 动画效果 <rotate/> RotateAnimation
  • Android- 动画 ( 缩放 )
    • 定义动画文件 res/anim/scale.xml
    • <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>
    • <set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>
    • < scale
    • android:interpolator=&quot;@android:anim/ accelerate_decelerate
    • _interpolato r &quot;
    • android:fromXScale=&quot;0.0&quot; // 起始时 X 轴比例 ( 相较于图片本身 )
    • android:fromYScale=&quot;0.0&quot;
    • android:toXScale=&quot;5&quot; // 结束时 y 轴 上的 比例
    • android:toYScale=&quot;5&quot;
    • android:pivotX=&quot;50%&quot; //x 轴轴心
    • android:pivotY=&quot;50%&quot; //y 轴轴心
    • android:fillAfter=&quot;false&quot; // 为 true ,该动画转化在动画结束后被应用
    • android:duration=&quot;5000&quot;/> // 持续时间 ( 毫秒 )
    • </set>
    • 注 : LinearInterpolator , Accelerateinterpolator , DecelerateInterpolator ,
    • 自 定义
  • Android- 动画 ( 缩放 )
    • 定义布局文件
    • <ImageView
    • android:layout_width=&quot;wrap_content&quot;
    • android:layout_height=&quot;wrap_content&quot;
    • android: src =&quot;@drawable/icon&quot;
    • android:id=&quot;@+id/imageView&quot;/>
    • // 加载动画 XML 文件 , 生成动画指令
    • Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
    • // 开始执行动画
    • imageView.startAnimation(animation);
    • // 编程式
    • ScaleAnimation animation = new ScaleAnimation(0.0f, 5f, 0.0f, 5f,
    • Animation.RELATIVE_TO_SELF, 0.5f,
    • Animation.RELATIVE_TO_SELF, 0.5f);
    • animation.setDuration(5000); // 设置持续时间 5 秒
    • imageView.startAnimation(animation);
  • Android- 动画 ( 透明 )
    • <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>
    • <set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>
    • < alpha
    • android:fromAlpha=&quot;0.1&quot;
    • android:toAlpha=&quot;1.0&quot;
    • android:duration=&quot;3000&quot;/>
    • </set>
    • AlphaAnimation animation = new AlphaAnimation(0.1, 1.0);
    • animation.setDuration(5000); // 设置持续时间 5 秒
    • imageView.startAnimation(animation);
  • Android- 动画 ( 移动 )
    • <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>
    • <set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>
    • < translate
    • android:repeatCount=&quot;2&quot;
    • android:fromXDelta=&quot;0&quot;
    • android:fromYDelta=&quot;0&quot;
    • android:toXDelta=&quot;120&quot;
    • android:toYDelta=&quot;120&quot;
    • android:duration=&quot;3000&quot;/>
    • </set>
    • TranslateAnimation animation = new TranslateAnimation(0, 120, 0, 120);
    • animation.setDuration(5000); // 设置持续时间 5 秒
    • imageView.startAnimation(animation);
  • Android- 动画 ( 旋转 )
    • <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>
    • <set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>
    • < rotate
    • android:interpolator=&quot;@android:anim/accelerate_interpolator&quot;
    • android:repeatCount=&quot;2&quot;
    • android:fromDegrees=&quot;0&quot;
    • android:toDegrees=&quot;+360&quot;
    • android:pivotX=&quot;50%&quot;
    • android:pivotY=&quot;50%&quot;
    • android:duration=&quot;3000&quot;/>
    • </set>
    • RotateAnimation animation = new RotateAnimation(0, -90, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    • animation.setDuration(500);
    • imageView.startAnimation(animation);
  • Android- 动画 (frame)
    • 准备图片 res/drawable/1.gif 2.gif..
    • res/ani/frame.xml
    • <?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?>
    • <animation-list
    • xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    • android:oneshot=&quot;false&quot;>
    • <item android:drawable=&quot;@drawable/girl_1&quot; android:duration=&quot;200&quot; />
    • <item android:drawable=&quot;@drawable/girl_3&quot; android:duration=&quot;200&quot; />
    • </animation-list>
    • imageView. setBackgroundResource (R.anim.frame);
    • animationDrawable = ( AnimationDrawable ) imageView. getBackground ();
    • public boolean onTouchEvent(MotionEvent event) {
    • if (event.getAction() == MotionEvent.ACTION_DOWN) {// 按下
    • animationDrawable.start();
    • return true;
    • }return super.onTouchEvent(event);
    • 注 :
  • 事件处理
      • onKeyDown
      • onTouchEvent
    • Activity
      • onResume 后
    • View
      • 设为焦点
  • Android- 手势识别
    • 添加视图监听器 ,
    • gestureOverlayView.addOnGesturePerformedListener();
    • mLibrary = GestureLibraries. fromRawResource (this, R.raw.gestures);
    • mLibrary.load();
    • gestureOverlayView = this.findViewById(R.id.gestures);
    • gestureOverlayView. addOnGesturePerformedListener (GestureListener());
    • mLibrary = GestureLibraries. fromRawResource (this, R.raw.gestures);
    • state = mLibrary. load (); // 加载手势库
    • interface GestureOverlayView.OnGesturePerformedListener{
    • public void onGesturePerformed(GestureOverlayView o,Gesture g) {
    • List<Prediction>=mLibrary.recognize(gesture);
    • Prediction prediction = predictions.get(0);
    • //prediction.score:0-100
    • //prediction.name: 名称
  • Android- 传感器
    • 传感器类型
    • 方向传感器 : Sensor.TYPE_ORIENTATION
    • 加速度 ( 重力 ) 传感器 : Sensor.TYPE_ACCELEROMETER
    • 光线传感器 : Sensor.TYPE_LIGHT
    • 磁场传感器 : Sensor.TYPE_MAGNETIC_FIELD
    • 距离 ( 临近性 ) 传感器 : Sensor.TYPE_PROXIMITY
    • 温度传感器 : Sensor.TYPE_TEMPERATURE
    • // 获取传感器
    • Sensor sensor =
    • sensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER );
    • // 注册监听 , 获取传感器变化值
    • sensorManager. registerListener (listener, sensor,
    • SensorManager.SENSOR_DELAY_GAME);
    • 注 :
    • 上面第三个参数为采样率 : 最快 , 游戏 , 普通 , 用户界面 . 当应用程序请求特定的采样率时 , 其
    • 实只是对传感器子系统的一个建议 , 不保证特定的采样率可用。
  • Android- 传感器
    • // 获取感应器管理器
    • sensorManager = (SensorManager) getSystemService ( SENSOR_SERVICE );
    • accelerometer = (TextView) findViewById(R.id.accelerometer);
    • orientation = (TextView) findViewById(R.id.orientation);
    • protected void onResume() {
    • // 获取重力加速度传感器
    • Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    • sensorManager. registerListener (listener, sensor, SensorManager.SENSOR_DELAY_GAME);
    • // 获取方向传感器
    • Sensor sensor1 = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
    • sensorManager.registerListener(listener, sensor1,SensorManager.SENSOR_DELAY_GAME);
    • super.onResume();
    • }
  • Android- 传感器
    • 注册监听器
    • private SensorEventListener listener = new SensorEventListener() {
    • public void onSensorChanged(SensorEvent event) { float x = event.values[ SensorManager.DATA_X ];
    • float y = event.values[ SensorManager.DATA_Y ];
    • float z = event.values[ SensorManager.DATA_Z ];
    • switch ( event.sensor.getType ()) {
    • case Sensor.TYPE_ACCELEROMETER :
    • break;
    • case Sensor.TYPE_ORIENTATION :
    • break;
    • }
    • }
    • public void onAccuracyChanged(Sensor sensor, int accuracy) {
    • }
    • };
    • }
  • Android Application
    • Application 就是 Activity , Service 之类的组件上下文描述
    • Activity , Broadcast Intent Receiver ,服务( Service ),内容提供器( Content Provider )。这些组件依附于应用程序中
    • 应用程序并不会一开始就建立起来,而是在这些组件建立起来后,需要运行时,才开始建立应用程序对象
  • Activity 所绑定的进程名称
    • android:name=&quot;string&quot;
    • android:process=&quot;string&quot;
    • . . .
    • Activity Manager Service 在应用程序的第一个组件需要运行时将会为应用程序建立一个进程,而这个进程的名字就是 android:process=”string” 所指定,缺省的是应用程序包的名字
    • 在建立 Actvitiy 时,如果在应用进程端没有应用对象,系统在该过程中利用 makeApplication 建立一个 Application 对象,实例化 &quot;android.app.Application&quot; ,建立一个应用程序上下文完成例如资源, package 等信息管理。
  • 进程与生命周期
    • Android 系统会尽可能长的延续一个应用程序进程,但在内存过低的时候,仍然会不可避免需要移除旧的进程。为决定保留或移除一个进程, Android 将每个进程都放入一个“重要性层次”中,依据则是它其中运行着的组件及其状态。重要性最低的进程首先被消灭,然后是较低的,依此类推。重要性共分五层,依据重要性列表如下:
    • 1. 前台进程
    • 是用户操作所必须的。当满足如下任一条件时,进程被认为是处于前台的:
    • 任一时间下,仅有少数进程会处于前台,仅当内存实在无法供给它们维持同时运行时才会被杀死。一般来说,在这种情况下,设备已然处于使用虚拟内存的状态,必须要杀死一些前台进程以用户界面保持响应。
    • 2. 可视进程
    • 没有前台组件,但仍可被用户在屏幕上所见。当满足如下任一条件时,进程被认为是可视的:、
    • o 它包含着一个不在前台,但仍然为用户可见的 activity (它的 onPause() 方法被调用)。这种情况可能出现在以下情况:比如说,前台 activity 是一个对话框,而之前的 activity 位于其下并可以看到。
    • o 它包含了一个绑定至一个可视的 activity 的服务。
    • 可视进程依然被视为是很重要的,非到不杀死它们便无法维持前台进程运行时,才会被杀死。
    • 3. 服务进程
    • 是由 startService() 方法启动的服务,它不会变成上述两类。尽管服务进程不会直接为用户所见,但它们一般都在做着用户所关心的事情(比如在后台播放 mp3 或者从网上下载东西)。所以系统会尽量维持它们的运行,除非系统内存不足以维持前台进程和可视进程的运行需要。
    • 4. 背景进程
    • 包含目前不为用户所见的 activity ( Activity 对象的 onStop() 方法已被调用)。这些进程与用户体验没有直接的联系,可以在任意时间被杀死以回收内存供前台进程、可视进程以及服务进程使用。一般来说,会有很多背景进程运行,所以它们一般存放于一个 LRU (最后使用)列表中以确保最后被用户使用的 activity 最后被杀死。如果一个 activity 正确的实现了生命周期方法,并捕获了正确的状态,则杀死它的进程对用户体验不会有任何不良影响。
    • 5. 空进程
    • 不包含任何活动应用程序组件。这种进程存在的唯一原因是做为缓存以改善组件再次于其中运行时的启动时间。系统经常会杀死这种进程以保持进程缓存和系统内核缓存之间的平衡。
    • Android 会依据进程中当前活跃组件的重要程度来尽可能高的估量一个进程的级别。比如说,如果一个进程中同时有一个服务和一个可视的 activity ,则进程会被判定为可视进程,而不是服务进程。
    • 此外,一个进程的级别可能会由于其它进程依赖于它而升高。一个为其它进程提供服务的进程级别永远高于使用它服务的进程。比如说,如果 A 进程中的内容提供者为进程 B 中的客户端提供服务,或进程 A 中的服务为进程 B 中的组件所绑定,则 A 进程最低也会被视为与进程 B 拥有同样的重要性。
  • ActivityThread
    • 应用进程不是 Application 而是 ActivityThread 。从实际的应用堆栈可以看到:
    • NaiveStart.main()
    • ZygoteInit.main
    • ZygoteInit$MethodAndArgsCall.run
    • Method.Invoke
    • method.invokeNative
    • ActivityThread.main()
    • Looper.loop()
    • 每个应用程序都以 ActivityThread.main() 为入口进入到消息循环处理
    • 应用程序通过 ActivityThread 提供的框架,建立消息循环 Looper 和 Handler
    • ActivityThread 建立与 Activity Manager Service (简称 AMS )的通讯接口
    • 默认的线程为主线程,主线程负责 UI 及事件处理。每个线程中都有一个 Looper ,循环处理本线程的消息队列。线程之间通过消息通讯。主线程中也可以创建辅助线程,但辅助线程不能直接操作 UI ,可以线程中创建 Looper ,通过消息进行。
    •  
    进程中的线程 APK Package Process Thread Looper Message Queue Thread External Service Calls Intent Receiver Activity Activity UI Events System Events Local Service Call
  • Android 消息系统 Loop Handler
    • Android 消息系统使用了 Looper , MessageQueue,Handler 等概念 ,Handler 先进先出原则。 Looper 类用来管理特定线程内对象之间的消息交换 (Message Exchange) 。
      • Looper: 一个线程可以产生一个 Looper 对象,由它来管理此线程里的 Message Queue( 消息队列 ) 。 Looper 只是产生一个消息循环框架,首先 Looper 创建了消息队列并把它挂接在 Linux 的线程上下文中,进入到取消息,并分发消息的循环当中
      • Handler: Handler 对象在同一个线程上下文中取得消息队列,对消息队列进行封装操作,最主要的就是 SendMessage 和担当起 dispatchMessage 这个实际工作。外部系统需要向某个 Android 线程发送消息,必须通过属于该 AndroidThread 的 Handler 这个对象进行。
      • Message Queue( 消息队列 ): 用来存放线程放入的消息。
      • 线程: UI thread 通常就是 main thread ,而 Android 启动程序时会替它建立一个 Message Queue
  • Activity 的四个状态
    • Active/Runing 一个新 Activity 启动入栈后,它在屏
    • 幕最前端,处于栈的最顶端,此时它处于可见并可和用户交互
    • 的激活状态。
    • 2. Paused 当 Activity 被另一个透明或者 Dialog 样式的
    • Activity 覆盖时的状态。此时它依然与窗口管理器保持连接,
    • 系统继续维护其内部状态,所以它仍然可见,但它已经失
    • 去了焦点故不可与用户交互。
    • 3. Stoped 当 Activity 被另外一个 Activity
    • 覆盖、失去焦点并不可见时处于 Stoped 状态。
    • 4. Killed Activity 被系统杀死回收或者没有被启动时处于
    • Killed 状态。
  • Activity 的各个回调函数与状态 之间的关系
    • protected void onCreate(Bundle savedInstanceState);
    • protected void onStart();
    • protected void onResume();
    • protected void onPause();
    • protected void onStop();
    • protected void onDestroy();
    • 在 Android 中 , 应用的响应性被
    • 活动管理器 (Activity Manager) 和
    • 窗口管理器 (Window Manager
      • ( 这两个系统服务所监视 .
      • 当用户触发了输入事件 ( 如键盘输入 , 点击按钮等 ),
      • 如果应用 5 秒内没有响应用户的输入事件 , 那么 ,Android 会认
      • 为该应用无响应 , 便弹出 ANR(Application No Response)
      • 在正常情况下 ,Android 程序会在一条单线程里运行 . 如果 Activity 要处理一件比较耗时的工作 , 应
      • 该交给子线程完成 , 否侧会因为主线程被阻塞 , 后面的用户输入事件因没能在 5 秒内响应 , 导致应用出现
    Android- 应用程序的响应性
  • Intent
  • Intent 跟 pendingIntent 间的联系
    • intent 执行后的操作。常和 alermanger 和 notificationmanager 一起使用。 Intent 一般是用作 Activity 、 Sercvice 、 BroadcastReceiver 之间传递数据,而 Pendingintent ,一般用在 Notification 上,可以理解为延迟执行的 intent ,
    • PendingIntent 是对 Intent 一个包装。
  • BroadcastReceiver 简介
    • BroadcastReceiver 的作用:每个 Broadcast Receiver 都可以接收
      • 一种或若干种 Intent 作为触发事件
    • BroadcastReceiver 不执行任何任务,仅仅是接受并响应广播
      • 通知的一类组件。
    • BroadcastReceiver 不包含任何用户界面
  • Service 简 介
    • 是什么:
      • Service 在 Android 中是一种长生命周期的组件,它不实现
      • 任何用户界面
    • 用来做什么:
      • 实现不需要用户界面但是需要一直运行的功能,如:音乐播放器
    • 怎么用:
      • 实现一个自己的 service
      • 启动执行: context.startService()/context.bindService()
  • Service 的生命周期
  • Android- 与服务进行进程间通信
    • 客户端和服务通过 IBinder 对象联系在一起 .bindService() 方法调用时 , 需要 Intent,
    • ServiceConnection 和 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--> .aidl)
    • //IDownloadService.aidl, 注意扩展名
    • package cn.shen.aidl;
    • interface IDownloadService {
    • void download(in/out/inout String path); //in|out|inout 是参数的方向
    • }
    • ide 会自动在 gen 包下生成对应的 java 类 , 接口文件中生成一个 Stub 的抽象类 , 里面包括 aidl 定义的
    • 方法 , 还包括一些其它辅助方法 . 值得关注的是 asInterface(IBinder iBinder), 它返回接口类
    • 型的实例 , 对于远程服务调用 , 远程服务返回给客户端的对象为代理对象 , 客户端 onServiceConnec
    • ted(ComponentName name, IBinder service) 方法引用该对象时不能直接强转成接口类型的
    • 实例 , 而应该使用 asInterface(IBinder iBinder) 进行类型转换 .
  • Android-AIDL 实现进程间通信
    • 编写 AIDL 需要注意 :
    • 1. 接口名和 aidl 文件名相同 .
    • 2. 接口和方法前不用加访问权限修饰符 public,private,protected 等 , 也不能用
    • final,static.
    • 3.Aidl 默认支持的类型包话 java 基本类型 (int,long,boolean 等 ) 和 (String,List,Map,
    • CharSequence), 使用这些类型时不需要 import 声明 . 对于 List 和 Map 中的元素类型必须是
    • Aidl 支持的类型 . 如果使用自定义类型作为参数或返回值 , 自定义类型必须实现 Parcelable 接
    • 口 .
    • 4. 自定义类型和 AIDL 生成的其它接口类型在 aidl 描述文件中 , 应该显式 import, 即便在该类和定义的包在同一个包中 .
    • 5. 在 aidl 文件中所有非 Java 基本类型参数必须加上 in 、 out 、 inout 标记 , 以指明参数是输入参数、输出参数还是输入输出参数 .
    • 6.Java 原始类型默认的标记为 in, 不能为其它标记 .
  • Android-AIDL 实现进程间通信
    • javabean 必须实现 Parcelable 接口
    • class Person implements Parcelable {
    • id,name; //get/set
    • public int describeContents () {
    • return 0;
    • }
    • // 把 javanbean 中的数据写到 Parcel
    • public void writeToParcel (Parcel dest, int flags) { dest.writeInt(this.id);
    • dest.writeString(this.name);
    • }
    • // 添加一个静态成员 , 名为 CREATOR, 该对象实现了 Parcelable.Creator 接口
    • public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>(){
    • public Person createFromParcel(Parcel source) { return new Person(source.readInt(), source.readString());
    • }
    • public Person[] newArray(int size) {
    • return new Person[size];
    • }};
    • }
  • Android-AIDL 实现进程间通信
    • 在自定义类型包中定义 aidl 声明文件
    • //Person.aidl, 注意 parcelable 是小写
    • package cn.shen.domain;
    • parcelable Person;
    • 接口定义文件需要显式导入自定义类型 ( 即时在同一个包下 ).
    • //PersonService.aidl
    • package cn.shen.aidl;
    • import cn.shen.domain.Person;
    • interface IPersonService {
    • void save(in Person person);
    • }
    • 创建 aidl 接口实现类 ( 通过继承 ${ 业务接口 }.stub 类实现 )
    • public class ServiceBinder extends IPersonService. Stub {
    • public void save(Person person) throws RemoteException {
    • Log.i(&quot;PersonService&quot;, person.getId()+&quot;=&quot;+ person.getName());
    • }
    • }
  • Android-AIDL 实现进程间通信
    • 实现 service 的 onBind 方法 . 返回值就是上一步创建的 aidl 实现类对象 .
    • public IBinder onBind(Intent intent) {
    • return new ServiceBinder ();
    • }
    • 客户端通过隐式意图访问服务 .
    • <service android:name=&quot;.PersonService&quot;>
    • <intent-filter>
    • <action android:name=&quot;cn.shen.process.aidl.PersonService&quot; />
    • new Intent(&quot;cn.shen.process.aidl.PersonService&quot;);
    • 复制 aidl 文件和所在包到客户端对应的 src 下 .( 客户端会自动生成对应 java 类 )
    • this.bindService(,this.sc,BIND_AUTO_CREATE);
    • sc = new ServiceConnection() {
    • public void onServiceConnected(ComponentName,IBinder service) {
    • personService = IPersonService.Stub.asInterface(service) ;
    • personService.save(new Person(56,&quot;liming&quot;));
    • }
    • public void onServiceDisconnected(ComponentName name) {
    • personService = null;
    • }};
  • IPC 框架分析
    • Android 的设计 Activity 托管在不同的的进程, Service 也都是托管在不同的进程,不同进程间的 Activity,Service 之间要交换数据属于 IPC 。
    • Binder 就是为了 Activity 通讯而设计的一个轻量级的 IPC 框架。
    • Binder 是一个很低层的概念,上面一层根本都看不到 Binder ,而是 Activity 跟一个 Service 的对象直接通过方法调用,获取服务
  • IPC- 对象请求代理架构
    • 在 Android 中,要完成某个操作,所需要做的就是请求某个有能力的服务对象去完成动作,而无需知道这个通讯是怎样工作的,以及服务在哪里。
    • Andoid 的 IPC 在本质上属于对象请求代理架构, Android 的设计者用 CORBA 的概念将自己包装了一下,实现了一个微型的轻量级 CORBA 架构
    • 只是解决本机的进程间的通讯
  • Android 的对象代理结构 Service Manager 提供了 add service check service 两个重要的方法,并且维护了一个服务列表记录登记的服务名称和句柄 这样 client 应用能够找到所需要的 service
  • Binder architecture Binder java Binder c++ Java binder framework Native binder framework Binder core system BBinder->IBinder<-BpBinder Binder Adapter IPCThreadeState,ProcessState Binder linux driver
  • Binder 核心类
    • IBinder
      • 虚拟类
    • BBinder
      • BBinder 有 onTransact 消息处理函数
    • BpBinder
      • BpBinder 有消息传递函数 transcat
  • Service 闭合循环框架
    • Android 设计中, Native Service 和 Android Service 采用了同一个闭合循环框架。这个闭合循环框架放置在 Native 的 C++ 空间中, ,ProcessState@ProcessState.cpp  和 [email_address] 两个类完成了全部工作。
    • 关于 ProcessState 和 IPCThreadState 在系统开发课程介绍
  • Android 启动过程
    • (1) init 进程启动
    • (2) Native 服务启动
    • (3) System Server , Android 服务启动
    • (4) Home 启动
    • 文件操作
    • Preferences 􁮘􀹄
    • SQLite 库存储
    • 网络
    • content provider
    Android 中的数据保存
  • 文件操作
    • openFileInput
    • openFileOutput
    • 读取资源文件
    • getResource().openRawResource(R.raw.xxx)
  • Preferences
    • 轻量级的
    • 保存的是原始数据类型
    • 常用于保存程序配置信息
    SharedPreferences settings = getSharedPreferences( SETTING_INFOS, 0); String name = settings.getString( NAME, &quot;&quot;); String password = settings.getString( PASSWORD, &quot;&quot;);
    • 过 Context.getSharedPreferences() 得到一个
    • SharedPreferences 。
    • 获取一个 Editor ,对保存的参数进行编辑:
    • commit() ,进行提交。
    • SharedPreferences settings = getSharedPreferences(“info”, 0);
    • Editor editor = settings.edit();
    • editor.putString(“name”, nameEditText.getText().toString())
    • .putString(“pwd”, passwordEditText.getText().toString())
    • .commit();
  • Android- 使用嵌入式 SQLite
    • Android 平台上集成 的 一个嵌入式关系型数据库 , SQLite3 支持 NULL,INTEGER,REAL (浮点数字) ,TEXT( 字符串文本 ) 和 BLOB( 二进制对象 ) 数据类型 , 虽然它支持的类型只有五种 , 但实际上 sqlite3 也接受 varchar(n),char(n),decimal(p,s) 等数据类型 , 只不过在运算或保存时会转成对应的五种数据类型 .
    • 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 3,5
  • Android- 使用嵌入式 SQLite
    • 首次使用数据库需要创建表及初始化一些信息 , 升级时需要修改表信 ,android 提供了抽象类 SQLiteOpenHelper 完成此类功能 .
    • onCreate(SQLiteDatabase db) 方法用于首次使用时创建库 ,
    • onUpgrade(SQLiteDatabase db, int oldVersion, int ewVersion) 方法检测版本发生变化时更新库 .
    • getWritableDatabase() 和 getReadableDatabase() 方法均获取一个用于操作数据库的 SQLiteDatabase 实例 .
    • getWritableDatabase() 方法以读写方式打开数据库 , 一旦数据库的磁盘空间满了 , 数据库就只能读而不能写 . 倘若使用 getWritableDatabase() 打开数据库就会出错 .getReadableDatabase() 方法先以读写方式打开数据库 , 如果数据库的磁盘空间满了 , 就会打开失败 , 当打开失败后会继续尝试以只读方式打开数据库 .
  • Android- 单元测试
    • <application android:icon=&quot;@drawable/icon&quot; package =&quot;...&quot; >
    • <uses-library android:name=&quot;android.test.runner&quot; />
    • ....
    • </application>
    • < instrumentation android:name=&quot;android.test.InstrumentationTestRunner&quot;
    • android:targetPackage =&quot;cn.shen.action&quot;
    • android:label=&quot;Tests for My App&quot; />
    • public class XMLTest extends AndroidTestCase {
    • public void testSomething() throws Throwable {
    • Log.i(&quot;Test&quot;, &quot;this is test 日志 &quot;);
    • System.out.println(&quot;ddd&quot;);
    • Assert.assertTrue(1 + 1 == 3);
    • }
    • }
  • Android-SQLite3 工具使用
    • <TableLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    • android:layout_width=&quot;fill_parent&quot;
    • android:layout_height=&quot;wrap_content&quot;
    • android:stretchColumns=&quot;0,1,2,3&quot;
    • android:id=&quot;@+id/tlList&quot;>
    • </TableLayout>
  • ContentProvider 简介
    • ContentProvider 是 Android 提供的一种标准的共享数据的机制 ,
    • 应用程序可以通过 content provider 访问其它应用程序的一些私有数据
    • ContentProvider 的优点:屏蔽了内部数据的存储细节,向外提供
    • 了上述统一的接口模型
  • Android- 使用 ContentProvider
    • 使用内容供应商共享数据 .
    • 如果直接访问磁盘文件 (SDCard|File|SQLite 数据库 | 首选项 ), 需要很多底层的交互细节 , 但是用
    • 该种方式 , 只使用 url 即可对应用程序进行访问 , 并统一了数据访问方式 .
    • public class PersonContentProvider extends ContentProvider{
    • public boolean onCreate()
    • public Uri insert( Uri uri, ContentValues values)
    • ...
    • }
    • <application android:icon=&quot;@drawable/icon&quot;
    • android:label=&quot;@string/app_name&quot;>
    • <!-- 注册供应商 -->
    • <provider android:name=&quot;.PersonContentProvider&quot;
    • android: authorities =&quot;cn.lg.providers.personprovider&quot;/>
    • </application>
  • Android- 使用 ContentProvider
  • Android- 活动墙纸
    • 活动墙纸是 android2.1 新增的特性 . 活动墙纸实质上是一个包含有 WallpaperService 的 android
    • 应用 . 该服务必须含有一个 WallpaperService.Engine, 该 Engine 是用户 ,surface 和系统之间的
    • 桥梁 . 他拥有绘制墙纸的 surface.
    • 首要的是 ,WallpaperService 必须携带内部 Engine 类进行创建 . 而且需要使用
    • android.service.wallpaper.WallpaperService 意图声明在清单文件中 , 以备设备识别为活
    • 动墙纸 . 需要关联 android.permission.BIND_WALLPAPER 权限到活动墙纸给 android 主程序 .
    • <service
      • android:name=&quot;LiveWallpaperService&quot;
      • android:enabled=&quot;true&quot;
      • android:icon=&quot;@drawable/icon&quot;
      • android:label=&quot;@string/app_name&quot;
      • android:permission=&quot;android.permission.BIND_WALLPAPER&quot; >
      • <intent-filter android:priority=&quot;1&quot; >
      • <action android:name=&quot;android.service.wallpaper.WallpaperService&quot; />
      • </intent-filter>
      • <meta-data
      • android:name=&quot;android.service.wallpaper&quot;
      • android:resource=&quot;@xml/wallpaper&quot; />
    • </service>
  • Android- 活动墙纸
    • 墙纸描述文件
    • 添加文件 /res/xml/wallpaper.xml, 描述活动墙纸 .
    • <meta-data android:name=&quot;android.service.wallpaper&quot;
    • android:resource=&quot;@xml/wallpaper&quot; />
    • <?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?>
    • <wallpaper xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
      • android:thumbnail=&quot;@drawable/thumbnail&quot;
      • android:description=&quot;@string/description&quot;
      • android:settingsActivity=&quot;PreferenceActivity&quot;/>
  • 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)
    • }
  • Widget
    • <receiver android:name= &quot;MeWidgetProvider&quot; android:icon= &quot;@drawable/boot_robot&quot;
        • android:label= &quot;AppWidget Life&quot; >
    • <intent-filter>
    • <action android:name= &quot;android.appwidget.action.APPWIDGET_UPDATE&quot; >
    • </action>
    • <category android:name= &quot;android.intent.category.DEFAULT&quot; ></category>
    • </intent-filter>
    • <meta-data android:resource= &quot;@xml/app_widget_info&quot;
    • android:name= &quot;android.appwidget.provider&quot; >
    • </meta-data>
    • </receiver>
  • 获取手机所有连接管理对象
    • public static boolean checkNet(Context context)
    • {// 获取手机所有连接管理对象(包括对 wi-fi,net 等连接的管理)
    • try {
    • ConnectivityManager connectivity = (ConnectivityManager) context
    • .getSystemService(Context.CONNECTIVITY_SERVICE);
    • if (connectivity != null) {
    • // 获取网络连接管理的对象
    • NetworkInfo info = connectivity.getActiveNetworkInfo();
    • if (info != null&& info.isConnected()) {
    • // 判断当前网络是否已经连接
    • if (info.getState() == NetworkInfo.State.CONNECTED) {
    • return true;
    • } } }
    • } catch (Exception e) {
    • }
    • return false;
    • }
  • 检查网络状态变化
    • <receiver android:name= &quot;itcast.util.NetCheck&quot;>
    • <intent-filter>
    • <action android:name= &quot;android.net.conn.CONNECTIVITY_CHANGE&quot;/>
    • </intent-filter>
    • </receiver>
    • public class NetUtil extends BroadcastReceiver{
    • public void onReceive( Context context, Intent intent )
    • {
    • ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService( Context. CONNECTIVITY_SERVICE );
    • NetworkInfo info = connectivityManager.getActiveNetworkInfo();
    • if (info != null&& info.isConnected()) {
    • // 判断当前网络是否已经连接
    • if (info.getState() == NetworkInfo.State. CONNECTED) {
    • Toast. makeText( context, &quot;ok&quot;, Toast.LENGTH_SHORT ).show();
    • } else
    • {
    • Toast. makeText( context, &quot;err&quot;, Toast.LENGTH_SHORT ).show(); }
    • } else
    • {
    • Toast. makeText( context, &quot;err&quot;, Toast.LENGTH_SHORT ).show();
    • } } }
    • }
    • <uses-permission android:name= &quot;android.permission.INTERNET&quot;></uses-permission>
    • <uses-permission android:name= &quot;android.permission.ACCESS_NETWORK_STATE&quot;/>
  • AsyncTask
    • 匿名线程的方式是存在缺陷的:
    • 第一,线程的开销较大,如果每个任务都要创建一个线程,那么应用程序的效率要低很多;
    • 第二,线程无法管理,匿名线程创建并启动后就不受程序的控制了,如果有很多个请求发送,那么就会启动非常多的线程,系统将不堪重负。另外,前面已经看到,在新线程中更新 UI 还必须要引入 handler ,这让代码看上去非常臃肿。
    •        
    • 为了解决这一问题, Android 在 1.5 版本引入了 AsyncTask 。
    • AsyncTask 的特点是任务在主线程之外运行,而回调方法是在主线程中执行,这就有效地避免了使用 Handler 带来的麻烦。阅读 AsyncTask 的源码可知, AsyncTask 是使用 java.util.concurrent 框架来管理线程以及任务的执行的, concurrent 框架是一个非常成熟,高效的框架,经过了严格的测试。这说明 AsyncTask 的设计很好的解决了匿名线程存在的问题。
  • AsyncTask 是抽象类
    • doInBackground(Params... p) ,在此方法中实现任务的执行工作,比如连接网络获取数据等。通常还应该实现
    • onPostExecute(Result r) 方法,因为应用程序关心的结果在此方法中返回。需要注意的是 AsyncTask 一定要在主线程中创建实例。
      • AsyncTask 定义了三种泛型类型 Params , Progress 和 Result 。
        • Params 启动任务执行的输入参数,比如 HTTP 请求的 URL 。
        • Progress 后台任务执行的百分比。
        • Result 后台执行任务最终返回的结果,比如 String 。
      • onPreExecute()
        • 当任务执行之前开始调用此方法,可以在这里显示进度对话框
      • doInBackground(Params...)
        • 此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用 publicProgress(Progress...) 来更新任务的进度。
      • onProgressUpdate(Progress...)
        • 此方法在主线程执行,用于显示任务执行的进度。
      • onPostExecute(Result)
        • 此方法在主线程执行,任务执行的结果作为此方法的参数返回
  • Android- 互联网 ( 多线程下载 )
    • 1. 多线程下载
    • // 取得下载文件大小 , 并构建随机访问文件
    • HttpURLConnection.getContentLength();
    • RandomAccessFile file = new RandomAccessFile(&quot;QQWubiSetup.exe&quot;,&quot;rwd&quot;);
    • file.setLength(filesize);// 设置本地文件的长度
    • // 设置每个线程连接的请求属性 range 为指定范围
    • HttpURLConnection.setRequestProperty( &quot;Range&quot;, &quot;bytes=2097152-4194303&quot; );
    • // 定位文件位置写入信息 .
    • file.seek(2097152);
    • file.write(..);
    • 注 : 多线程下载时 , 不要判断 200 值 .
    • style=&quot;@android:style/Widget.ProgressBar.Horizontal&quot;
    • <style name=&quot;Widget.ProgressBar.Horizontal&quot;>
    • <item name=&quot;android:indeterminateDrawable&quot;>
    • @android:drawable/progress_indeterminate_horizontal</item>
    • <item name=&quot;android:minHeight&quot;>20dip</item>
    • <item name=&quot;android:maxHeight&quot;>20dip</item>
    • </style>
    • 动态添加进度条时 , 指定的是 android.R.attr.progressBarStyleHorizontal 样式值 .
  • ListView 优化
    • public class WeiboStatuAdapter extends BaseAdapter{
    • public Context con;
    • public List<Status> alls;
    • public LayoutInflater lif;
    • public WeiboStatuAdapter(Context con,List<Status> as)
    • { this.con=con;
    • lif=LayoutInflater. from(con);
    • this.alls=as;
    • }
    • public int getCount() {return alls.size()+2; }
    • public Object getItem(int arg0) {return null; }
    • public long getItemId(int index) {
    • if(index==0)// 选中第一项
    • { return 0;
    • } else if(index>0&&(index<this.getCount()-1))
    • { return alls.get(index-1).getId();// 如果用户选中了中间项
    • } else{
    • return -1;// 表示用户选中最后一项
    • }}
    • // 增加更多的数据
    • public void addMoreData(List<Status> moreStatus)
    • { this.alls.addAll(moreStatus);// 把新数据增加到原有集合
    • this.notifyDataSetChanged();
    • }
  • Android- 多媒体 ( 照相机 )
    • this.requestWindowFeature(Window.FEATURE_NO_TITLE); // 无标题
    • Window w = this.getWindow();
    • w.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    • WindowManager.LayoutParams.FLAG_FULLSCREEN); // 设置全屏
    • w.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); // 高亮
    • surfaceView.getHolder().setFixedSize(176, 144); // 设置分辨率
    • surfaceView.getHolder().setType( SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS );
    • surfaceView.getHolder().addCallback(); // 回调
    • WindowManager wm = getSystemService( Context.WINDOW_SERVICE ); // 窗口管理器
    • Display display = wm.getDefaultDisplay(); //
    • Camera camera = Camera.open(); // 打开照相机
    • Camera.Parameters parameters = camera.getParameters();
    • parameters.setPreviewSize(display.getWidth(),display.getHeight()); // 大小
    • parameters.setPreviewFrameRate(3); // 每秒 3 帧
    • parameters.setPictureFormat( PixelFormat.JPEG ); // 设置照片的输出格式
    • parameters.set(&quot;jpeg-quality&quot;, 85); // 照片质量
    • parameters.setPictureSize(display.getWidth(),display.getHeight());
    • camera.setParameters(parameters);
  • Android- 多媒体 ( 照相机 )
    • // 通过 SurfaceView 显示取景画面
    • camera.setPreviewDisplay(surfaceView.getHolder());
    • camera.startPreview(); // 开始预览
    • camera.autoFocus(null); // 自动对焦
    • camera.takePicture(null, null, null, jpegCallback); // 拍照片
    • camera.stopPreview(); // 停止预览
    • camera.release(); // 释放摄像头
    • onKeyDown:
    • public boolean onKeyDown(int keyCode, KeyEvent event) {
    • if(camera != null && event.getRepeatCount() == 0){
    • case KeyEvent.KEYCODE_SEARCH:
    • }
    • PictureCallback:
    • Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, data.length);
    • File jpg = new File(Environment.getExternalStorageDirectory(),&quot;1.jpg&quot;);
    • FileOutputStream fos = new FileOutputStream(jpg);
    • bmp.compress(Bitmap.CompressFormat.JPEG, 100,fos);
    • fos.close();
    • camera.startPreview();
  • Android- 多媒体 ( 照相机 )
    • 使用意图模拟拍照
    • 若没有摄像头硬件 , 可使用系统内置的 provider 实现摄像头功能 ( 该功能 2.2 的模拟器不支持 ).
    • Intent intent = new Intent(
    • android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
    • // 指定输出文件
    • //outputFileUri 指定照片存放的地址 , 若有的话存放全尺寸大照片 , 否则返回位图 .
    • // 在 onActivityResult 方法中接收
    • intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri );
    • startActivityForResult(intent, 0);
    • BitmapFactory.Options options = new BitmapFactory.Options();
    • options.inSampleSize = 1;
    • Bitmap bitmap = BitmapFactory.decodeFile(_path, options);
    • _image.setImageBitmap(bitmap);
    • <!-- 需要使用如下权限 -->
    • <uses-permission android:name=&quot;android.permission.CAMERA&quot; />
    • <uses-feature android:name=&quot;android.hardware.camera&quot; />
    • <uses-feature android:name=&quot;android.hardware.camera.autofocus&quot; />
    • Button btaddPic=(Button) this .findViewById(R.id. btGallery );
    • btaddPic.setOnClickListener( new OnClickListener()
    • {
    • @Override
    • public void onClick(View v) {
    • Intent i = new Intent(&quot;android.media.action.IMAGE_CAPTURE&quot;);
    • startActivityForResult(i, Activity. DEFAULT_KEYS_DIALER );
    • }
    • }
    • );
    • protected void onActivityResult( int requestCode, int resultCode, Intent data) {
    • // TODO Auto-generated method stub
    • super .onActivityResult(requestCode, resultCode, data);
    • Bundle extras = data.getExtras();
    • Bitmap b = (Bitmap) extras.get(&quot;data&quot;);
    • ByteArrayOutputStream baos = new ByteArrayOutputStream();
    • b.compress(Bitmap.CompressFormat. JPEG , 100, baos);
    • dat = baos.toByteArray();
    • this .hasPic= true ;
    • }
  • 地图开发
    • Google 地图
      • Google MAP
      • 位置导航
    • 第三方地图
      • 高德
    • 1. 获取指纹
    • C:Documents and SettingsAdministrator>cd C:Documents and SettingsAdministrat
    • or.android
    • C:Documents and SettingsAdministrator.android>keytool -list -keystore debug.kEystore
    • 默认密码 android
    • 2. 申请 apikey
    • http://code.google.com/intl/zh-CN/android/maps-api-signup.html
  • 使用 Google 地图
    • MapActivity
        • 任何显示 MapView 的 Activity 都要继承这个类
        • 内部封装了访问网络的方法
    • MapView
    • MapController
        • 控制地图的 移动和缩放
    • Overlay
    • GeoPoint
    • <uses-library android:name=“com.google.android.maps”>
    • <uses-permission android:name= &quot;android.permission.INTERNET&quot;></uses-permission>
    • MapView map=new MapView(this,”key”);
    • Map.setTraffic 地图模式
    • Map. setSatellite 卫星模式
    • Map.setStreetView 街景模式
    • MapControl=mMapview.getController();
    • geoPoint=new 成都 GeoPoint((int),30.65925*1000000, (int),104.065762*1000000,)
    • mMapController.animateTo(geoPoint);
    • Public class myLocationOverLay extends OverLay
    • {
    • public boolean draw(Canvas c,mapView m,boolean shadw,long when)
    • {
    • }
    • }
  • 定位系统
    • LocationManager
        • getSystemService(Conext.LOCATION_SERVICE)
        • 注册周期更新视图的侦听
        • Lm.requestLocationUpdates(Locationmanager.GPS_PROVIDER,1000,0,LocationListener)
    • LocationProvider
    • LocationListener
        • onLocationChanged
        • onProviderDisabled
        • onproviderEnabled
        • onStatusChanged
    • Criteria
    • GeoCoder
    • ( 1 ) public void setAccuracy( int accuracy )
    • 位置解析的精度,高或低,参数: Criteria. ACCURACY_FINE ,精确模式; Criteria. ACCURACY_COARSE ,模糊模式;
    • ( 2 ) public void setAltitudeRequired(boolean altitudeRequired )
    • 是否提供海拔高度信息,是或否
    • ( 3 ) public void setBearingRequired( boolean bearingRequired )
    • 是否提供方向信息,是或否
    • ( 4 ) public void setCostAllowed( boolean costAllowed )
    • 是否允许运营商计费,是或否
    • ( 5 ) public void setPowerRequirement( int level )
    • 电池消耗,无、低、中、高,参数 Criteria. NO_REQUIREMENT, Criteria. POWER_LOW, Criteria. POWER_MEDIUM, or Criteria. POWER_HIGH,
    • ( 6 ) public void setSpeedRequired( boolean speedRequired )
    • criteria.setAccuracy(ACCURACY_FINE)
    • ACCURACY_FINE
    • 精确度设置为模糊解决所有手机无法启动 Criteria.ACCURACY_COARSE
  • Android Ndk 开发
    • JNI 实现 NDK 定义的 native 方法调用
    • 1. 编写 Java 类定义 native 方法
    • 2. 通过 javah 命令生成类的 .h 文件
    • 3. 创建 c 的项目工程
    • 4. 编写 .c 的函数实现
    • 5. 编译生成 .so
    • 6. 拷贝 .so 到 java 项目中
    • 7. 在 static{
    • System.loadLaibrary(&quot;xxxx&quot;);
    • }
    • 8. 直接调用 native 方法
  • 应用程序的优化
      • 代码优化的关键
        • 少用 浮点运算 、 文件、 pipe 、数据库 访问
        • 用高效的方式: StringBuffer 代替大量临时 String ,
        • SoundPool 代替多个 MediaPlayer ,
        • texture 代替 canvas ,
        • Log.d() 代替 System.out.print() ,
        • 避免 invalidate()
        • 重视 onMeasure/onLayout/onDraw/onTouchEvent/getView 等函数的效率
      • 游戏开发
        • 少用 n ew ()/ enum / Iterator / HashMap / Arrays.sort ()/ Class.getXXX() … 
        • 多用 private 、 final 、局部变量 ,
        • 2D 善用 draw_texture 、 3D 善用 VBO 顶点缓冲
        • 触屏事件时,暂停接受运动感应事件
        • 用 NDK 实现关键代码
      • 不要求速度时,可用 WebView 和网页实现界面
      • 编译时执行代码优化
    • 谢谢