Ø 建立 Android Project javascript
Ÿ Project name :项目名 php
Ÿ Build Target : Android 版本 html
Ÿ Application name :程序名,显示在程序列表中,以及程序启动后的标题栏 前端
Ÿ Package name :包名,程序的惟一标识 java
Ÿ Create Activity :选择程序启动时是否建立一个窗体,设置主窗体名字 android
Ÿ Min SDK Version :设置运行该程序所需的最低版本 git
Ÿ Eclipse 安装 github
右键点击工程 – Run as – Android Applicationweb
Ÿ 虚拟机卸载sql
设置 – 应用程序 – 管理应用程序 – 选中要卸载的程序 – 卸载
Ÿ src :源代码
Ÿ gen :系统自动生成的文件
R.java 中记录了项目中各类资源 ID
Ÿ res :系统资源,全部文件都会在 R 文件生成资源 ID
drawable :图片
layout :界面布局
values :数据
anim :定义动画的 XML
raw :原生文件
Ÿ assets :资源路径,不会在 R 文件注册
Ÿ project.properties :供 Eclipse 使用,读取该项目使用 Android 版本号。早期版本名为: default.properties
Ÿ AndroidManifest.xml :清单文件,在软件安装的时候被读取
Android 中的四大组件( Activity 、 ContentProvider 、 BroadcastReceiver 、 Service )都须要在该文件中注册
程序所需的权限也须要在此文件中声明,例如:电话、短信、互联网、访问 SD 卡
Ÿ bin :二进制文件,包括 class 、资源文件、 dex 、 apk 等
Ÿ proguard.cfg:用来混淆代码的配置文件,防止别人反编译
Ÿ Eclipse 将 .java 源文件编译成 .class
Ÿ 使用 dx 工具将全部 .class 文件转换为 .dex 文件
Ÿ 再将 .dex 文件和全部资源打包成 .apk 文件
Ÿ 将 .apk 文件安装到虚拟机完成程序安装
Ÿ 启动程序 – 开启进程 – 开启主线程
Ÿ 建立 Activity 对象 – 执行 OnCreate() 方法
Ÿ 按照 main.xml 文件初始化界面
Ÿ Android 程序中若是出错,错误不会显示在 Console 中,而是显示在 LogCat 界面下。能够从 window – show view 中打开
Ÿ 日志信息分为 5 个级别: verbose > debug > info > warn > error 高级的包含低级的
Ÿ 能够建立过滤器对日志进行过滤显示,点击绿色加号,能够按照 tag 、 pid 、 level 进行筛选
Ø RelativeLayout (相对布局)
Ÿ android-sdk-windows/docs/guide/topics/ui/layout-objects.html#relativelayout
Ø TableLayout (表格布局)
android-sdk-windows/docs/guide/topics/ui/layout-objects.html#tablelayout
Ø FrameLayout (帧布局)
android-sdk-windows/docs/guide/topics/ui/layout-objects.html#framelayout
setRequestedOrientation(ActivityInfo. SCREEN_ORIENTATION_LANDSCAPE );
setRequestedOrientation(ActivityInfo. SCREEN_ORIENTATION_PORTRAIT );
Ø 项目中添加测试类
Ÿ 在 AndroidManifest.xml 清单文件中添加配置
< instrumentation android:targetPackage = "cn.itcast.junit" android:name = "android.test.InstrumentationTestRunner" />
< uses-library android:name = "android.test.runner" />
Ÿ 定义一个类继承 AndroidTestCase ,定义测试方法
Ÿ 在 Outline 视图下右键点击测试方法 – Run as – Android Junit Test
Ø 建立测试项目
Ÿ 建立 Android Test Project
Ÿ 输入项目名,选择一个已存在的工程, Eclipse 能够自动配置 Junit 环境
Ø 写入文件到 SD 卡
Ÿ 须要在清单文件中注册权限
< uses-permission android:name = "android.permission.WRITE_EXTERNAL_STORAGE" />
Ÿ 2.1 版本如下的 SDCard 位置和 2.2 以后版本不一样
能够经过Environment.getExternalStorageDirectory()获取当前 SDCard 位置,兼容全部版本
Ÿ 获取 SDCard 状态
经过Environment.getExternalStorageState()方法获取 SDCard 当前状态
常量 Environment.MEDIA_MOUNTED 为已安装
Ø 写入文件
Ÿ 经过 Context. openFileOutput(String name, int mode)能够获取一个文件输入流
name 为文件名, mode 为文件模式,有 4 种模式
输出流指向路径为: /data/data/ 包名 /files/
Ÿ 文件模式在 Context 中有定义常量
MODE_PRIVATE 私有
MODE_WORLD_READABLE 其余程序可读(不可写)
MODE_WORLD_WRITEABLE 其余程序可写(不可读)
模式能够组合使用,例如:MODE_WORLD_READABLE + MODE_WORLD_WRITEABLE
MODE_APPEND 追加
Ø 读取文件
Ÿ 经过 Context. openFileInput(String name)能够获取一个文件输入流
该输入流能够读取 /data/data/ 包名 /files/ 路径下的文件
Ÿ 获取当前程序 Files 文件路径
ContextWrapper.getFilesDir()
Ø Pull 简介
Ÿ 常见的 XML 解析方式有三种, DOM 、 SAX 、 Pull , Android 系统中推荐使用 Pull
Ÿ Pull 解析器是一个开源的 Java 项目, Android 系统内部解析 XML 文件均为此种方式,也可用于 JavaEE 项目
Ÿ Android SDK 中已经集成了 Pull 解析器,无需添加任何 jar 文件
Ÿ Pull 解析器运行方式与 SAX 相似,提供各类事件的判断
Ÿ 官方网站: http://xmlpull.org/
Ø 使用 Pull 解析器解析 XML 文件
Ÿ Xml.newPullParser() 得到解析器
Ÿ parser.setInput(in, "UTF-8" ) 设置输入流以及编码
Ÿ parser.next() 获取下一个解析事件,获得一个事件代码
Ÿ XmlPullParser中定义了常量来标识各类解析事件
START_DOCUMENT 、 END_DOCUMENT 、 START_TAG 、END_TAG 、 TEXT
Ø 使用XmlSerializer写出 XML
Ÿ 使用如下方法生成 XML ,和 XML 文档顺序相似
startDocument
startTag
attribute
text
endTag
endDocument
Ÿ 在程序中保存一些配置参数的时候咱们常用 SharedPreferences
Context.getSharedPreferences(String name, int mode)
该方法能够在 /data/data/<package>/shared_pref/ 目录下建立一个以 name 命名的 xml 文件, mode 文件为模式
Ÿ 存储偏好
调用edit()方法能够获取一个 Editor 对象,对数据进行存储,存储以后须要调用 commit()保存到文件
Ÿ 读取偏好
得到SharedPreferences以后调用 getString() 、 getInt() 等方法获取其中设置的值
Ÿ 在 Activity 中获取 SharedPreferences
在 Activity 中能够调用 getPreferences( int mode)方法得到一个SharedPreferences,文件名和 Activity 名一致
Ÿ Android 平台中嵌入了一个关系型数据库 SQLite ,和其余数据库不一样的是 SQLite 存储数据时不区分类型
例如一个字段声明为 Integer 类型,咱们也能够将一个字符串存入,一个字段声明为布尔型,咱们也能够存入浮点数。
除非是主键被定义为 Integer ,这时只能存储 64 位整数
Ÿ 建立数据库的表时能够不指定数据类型,例如:
CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20))
CREATE TABLE person(id INTEGER PRIMARY KEY AUTOINCREMENT, name)
Ÿ SQLite 支持大部分标准 SQL 语句,增删改查语句都是通用的,分页查询语句和 MySQL 相同
SELECT * FROM person LIMIT 20 OFFSET 10
SELECT * FROM person LIMIT 10,20
Ÿ 定义类继承SQLiteOpenHelper
Ÿ 声明构造函数, 4 个参数
Ÿ 重写 onCreate ()方法
Ÿ 重写 upGrade() 方法
Ÿ 注意: SQLite 数据库中列一旦建立不能修改,若是必定要修改,须要从新建立表,拷贝数据
Ÿ 和 JDBC 访问数据库不一样,操做 SQLite 数据库无需加载驱动,不用获取链接,直接可使用
获取 SQLiteDatabase 对象以后经过该对象直接能够执行 SQL 语句
SQLiteDatabase.execSQL()
SQLiteDatabase.rawQuery()
Ÿ getReadableDatabase()和getWritableDatabase()的区别
查看源代码后咱们发现getReadableDatabase()在一般状况下返回的就是getWritableDatabase() 拿到的数据库
只有在抛出异常的时候才会以只读方式打开
Ÿ 数据库对象缓存
getWritableDatabase() 方法最后会使用一个成员变量记住这个数据库对象,下次打开时判断是否重用
Ÿ SQLiteDatabase 封装了 insert() 、 delete ()、 update ()、 query ()四个方法也能够对数据库进行操做
这些方法封装了部分 SQL 语句,经过参数进行拼接
Ÿ 在使用 SQLite 数据库时能够用 SQLiteDatabase类中定义的相关方法控制事务
beginTransaction() 开启事务
setTransactionSuccessful() 设置事务成功标记
endTransaction() 结束事务
Ÿ endTransaction() 须要放在 finally 中执行,不然事务只有到超时的时候才自动结束,会下降数据库并发效率
Ÿ 内容提供者是 Android 中的四大组件之一,能够将应用中的数据对外进行共享
Ÿ 内容提供者将数据的访问方式统一,没必要针对不一样数据类型采起不一样的访问策略
Ÿ 内容提供者将数据封装,只暴露出咱们但愿提供给其余程序的数据
Ÿ 内容提供者中数据更改可被监听
Ÿ 定义类继承 ContentProvider ,根据须要重写内部方法
Ÿ 在清单文件的 <application> 节点下进行配置, <provider> 标签中须要指定 name 和 authorities 属性
name 为类名,包名从程序 Package 开始,以“ . ”开始
authorities :是访问 Provider 时的路径,要惟一
Ÿ URI 表明要操做的数据,由 scheme 、 authorites 、 path 三部分组成
content:// cn.itcast. sqlite . provider / person
scheme :固定为 content ,表明访问内容提供者
authorites : <provider> 节点中的 authorites 属性
path :程序定义的路径,可根据业务逻辑定义
Ÿ 当程序调用 CRUD 方法时会传入 Uri
Ÿ 咱们经过 Uri 判断调用者要操做的数据
可使用工具类 UriMatcher 来判断 Uri
addURI 方法能够添加 Uri
match 方法能够匹配一个 Uri 判断其类型
Ÿ 根据业务逻辑操做数据
Ÿ 经过 Context 得到 ContentResolver 对象
Ÿ 调用 ContentResolver 对象的方法便可访问内容提供者
Ÿ 若是返回数据是单条数据:vnd.android.cursor.item
Ÿ 若是返回数据是多条数据:vnd.android.cursor.dir
Ÿ 在内容提供者中能够通知其余程序数据发生变化
经过 Context 的 getContentResolver() 方法获取 ContentResolver
调用其notifyChange() 方法发送数据修改通知
Ÿ 在其余程序中能够经过ContentObserver监听数据变化
经过 Context 的 getContentResolver() 方法获取 ContentResolver
调用其registerContentObserver() 方法指定对某个 Uri 注册 ContentObserver
自定义ContentObserver,重写 onChange() 方法获取数据
Ø 资源地址
Ÿ Git
http://code.google.com/p/msysgit/
Ÿ 源码
注意:
GIT1.7.7 安装后不能卸载,能够用其余版本覆盖后再卸载。
使用 GIT 时不要使用中文目录,不然 GIT GUI 会报错没法启动。删除 C 盘中 .gitconfig文件能够解决。
Ÿ 经过 URL 对象封装地址,打开一个 HttpURLConnection
Ÿ 设置头信息以后获取响应码,若是成功返回 200 便可从 HttpURLConnection 中获取输入流读取数据
Ÿ 代码过长屏幕显示不全可使用 <ScrollView> 进行显示
Ÿ 须要访问网络的权限
< uses-permission android:name = "android.permission.INTERNET" />
Ÿ 经过 BitmapFactory 的 decodeByteArray(byte[] data, int offset, int length)方法将数据转换为图片对象
Ÿ 使用 URL 封装路径,打开一个 HttpURLConnection
Ÿ 设置头信息以后获取相应码,从输入流中获取数据
Ÿ 使用 XmlPullPaser 解析
Ÿ 使用 URL 封装路径,打开一个 HttpURLConnection
Ÿ 设置头信息以后获取相应码,从输入流中获取数据
Ÿ 将数据转为 String ,封装成 JSONArray 对象
Ÿ 遍历 JSONArray 对象,调用获取其中的 JSONObject
Ÿ 再从 JSONObject 中获取每一个字段的信息
Ÿ 拼接路径和参数,经过 URL 进行封装,打开一个 HttpURLConnection ,发送请求
Ÿ 若是参数是中文会出现乱码
Ÿ URL 中包含的中文参数须要使用 URLEncoder 进行编码
Ÿ 服务器端若是是 TOMCAT ,其默认使用 ISO8859-1 编码,接收时须要处理编码问题
Ÿ 经过 URL 打开一个 HttpURLConnection
Ÿ 头信息中除了超时时间和请求方式以外还必须设置Content-Type和Content-Length
Ÿ 从 HttpURLConnection 得到输出流输出参数数据
Ÿ 服务端可使用 request 对象的 setCharacterEncoding方法设置编码
Ø 发送 XML
Ÿ 经过 URL 封装路径打开一个 HttpURLConnection
Ÿ 设置请求方式,Content-Type和Content-Length
XML 文件的 Content-Type为:text/xml; charset=UTF-8
Ÿ 使用 HttpURLConnection 获取输出流输出数据
Ø WebService
Ÿ WebService 是发布在网络上的 API ,能够经过发送 XML 调用, WebService 返回结果也是 XML 数据
Ÿ WebService 没有语言限制,只要能够发送 XML 数据和接收 XML 数据便可
Ÿ http://www.webxml.com.cn 网站上提供了一些 WebService 服务,咱们能够对其进行调用
Ÿ http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?op=getMobileCodeInfo 中提供了电话归属地查询的使用说明
Ÿ 搭建服务器,完成上传功能
Ÿ 使用浏览器上传,查看请求信息
Ø HttpURLConnection
Ÿ 经过 URL 封装路径打开一个 HttpURLConnection
Ÿ 设置请求方式以及头字段:Content-Type、Content-Length、Host
Ÿ 拼接数据发送
Ø Socket
Ÿ 使用 HttpURLConnection 发送时内部有缓存机制,若是上传较大文件会致使内存溢出
Ÿ 咱们可使用 Socket 发送 TCP 请求,将上传数据分段发送
Ø HttpClient
public void upload(String name, String password, String path) throws Exception {
// 建立 HttpClient 对象
HttpClient client = new HttpClient();
// 设置超时事件
client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
// 建立一个 Post 请求 , 指定路径
PostMethod postMethod = new PostMethod( "http://192.168.1.102:8080/14.Web/LoginServlet" );
// 封装每一个表单项
Part[] parts = { new StringPart( "name" , name), new StringPart( "password" , password), new FilePart( "file" , new File(path)) };
// 给 Post 请求设置实体
postMethod.setRequestEntity( new MultipartRequestEntity(parts, postMethod.getParams()));
// 执行 Post 请求
client.executeMethod(postMethod);
// Post 请求是释放资源
postMethod.releaseConnection();
}
Ÿ 在下载的时候多个线程并发能够占用服务器端更多资源,从而加快下载速度
Ÿ 手机端下载数据时不免会出现无信号断线、电量不足等状况,因此须要断点续传功能
Ÿ 根据下载数据长度计算每一个线程下载的数据位置,程序中开启多个线程并发下载
在请求头中设置 Range 字段就能够获取指定位置的数据,例如: Range: bytes=100-200
Ÿ 在下载过程当中记录每一个线程已拷贝数据的数量,若是下载中断,下次启动时从记录位置继续下载
Ø 多线程下载
Ÿ 进度条使用 <Progress> 进行配置
默认为圆形进度条,水平进度条须要配置 style 属性, ?android:attr/progressBarStyleHorizontal
使用 android.R.attr. progressBarStyleHorizontal做为样式
Ÿ 当点击下载按钮时开启多线程下载,下载过程当中修改进度条进度
设置最大刻度:setMax()
设置当前进度:setProgress()
Ø 断点续传
Ÿ 断点续传须要在下载过程当中记录每条线程的下载进度
Ÿ 每次下载开始以前先读取数据库,查询是否有未完成的记录,有就继续下载,没有则建立新记录插入数据库
Ÿ 在每次向文件中写入数据以后,在数据库中更新下载进度
Ÿ 下载完成以后删除数据库中下载记录
Ø Handler 传输数据
Ÿ 主线程中建立的 View 只能在主线程中修改,其余线程只能经过和主线程通讯,在主线程中改变 View 数据
Ÿ 咱们使用 Handler 能够处理这种需求
主线程中建立 Handler ,重写 handleMessage() 方法
新线程中使用 Handler 发送消息,主线程便可收到消息,而且执行 handleMessage() 方法
Ø 动态生成新 View
Ÿ 建立 XML 文件,将要生成的 View 配置好
Ÿ 获取系统服务 LayoutInflater ,用来生成新的 View
LayoutInflater inflater = (LayoutInflater) getSystemService( LAYOUT_INFLATER_SERVICE );
Ÿ 使用inflate( int resource, ViewGroup root)方法生成新的 View
Ÿ 调用当前页面中某个容器的 addView ,将新建立的 View 添加进来
Ø 定义 Activity
Ÿ 定义类继承 Activity
Ÿ 在 AndroidManifest.xml 的 <application> 节点中声明 <activity>
Ø 显式意图建立方式
Ÿ 构造函数,代码少
new Intent( this , NewActivity. class );
Ÿ 类名形式,灵活,可扩展性强
intent.setClassName( this , "cn.itcast.activity.NewActivity" );
Ÿ 包名类名形式,可启动其余程序中的 Activity
intent.setClassName( "cn.itcast.downloader" , "cn.itcast.downloader.MainActivity" );
Ø 建立 Activity 并传递数据
Ÿ 在乎图对象中封装了一个 Bundle 对象,能够用来携带数据
Ÿ 在新 Activity 中能够得到意图对象以获取其中 Bundle 保存的数据
Ø 建立 Activity 获取返回数据
Ÿ 使用startActivityForResult(Intent intent, int requestCode) 方法打开 Activity
Ÿ 重写onActivityResult( int requestCode, int resultCode, Intent data) 方法
Ÿ 新 Activity 中调用 setResult( int resultCode, Intent data) 设置返回数据以后,关闭 Activity 就会调用 onActivityResult方法
Ø 隐式意图建立 Activity
Ÿ 显式意图是指在建立意图时指定了组件,而隐式意图则不指定组件,经过动做、类型、数据匹配对应的组件
Ÿ 在清单文件中定义 <activity> 时须要定义 <intent-filter> 才能被隐式意图启动
Ÿ <intent-filter> 中至少配置一个 <action> 和一个 <category> ,不然没法被启动
Ÿ Intent 对象中设置的 action 、 category 、 data 在 <intent-filter> 必须所有包含才能启动
Ÿ <intent-filter> 中的 <action> 、 <category> 、 <data> 均可以配置多个, Intent 对象中不用所有匹配,每样匹配一个便可启动
Ÿ 若是一个意图能够匹配多个 Activity , Android 系统会提示选择
Ÿ Acitivity 三种状态
运行: activity 在最前端运行
暂停: activity 可见,但前端还有其余 acti vity ,被覆盖一部分,或者前端 activity 透明
中止: activity 不可见,彻底被覆盖
Ÿ 生命周期相关方法
onCreate :建立时调用,或者程序在暂停、中止状态下被杀死以后从新打开时也会调用
onStart : onCreate 以后或者从中止状态恢复时调用
onResume : onStart 以后或者从暂停状态恢复时调用,从中止状态恢复时因为调用 onStart ,也会调用 onResume
onPause:进入暂停、中止状态,或者销毁时会调用
onStop:进入中止状态,或者销毁时会调用
onDestroy:销毁时调用
onRestart :从中止状态恢复时调用
Ÿ 保存信息相关方法
onSaveInstanceState:在 Activity 被动的摧毁或中止的时候调用,用于保存运行数据,能够将数据存在在 Bundle 中
onRestoreInstanceState:该方法在 Activity 被从新绘制的时候调用,例如改变屏幕方向, savedInstanceState为onSaveInstanceState保存的数据
Ÿ 在 AndroidManifest.xml 中的 <activity> 标签中能够配置 android:launchMode 属性,用来控制 Actvity 的启动模式
Ÿ 在 Android 系统中咱们建立的 Acitivity 是以栈的形式呈现的
standard :每次调用 startActivity() 启动时都会建立一个新的 Activity 放在栈顶
singleTop :若是启动的 Activity 时,指定 Activity 不在栈顶就建立,如在栈顶,则再也不建立
singleTask :若是启动的 Activity 不存在就建立,若是存在直接跳转到指定的 Activity 所在位置
singleInstance :若是启动的 Activity 不存在就建立,若是存在就将指定的 Activity 移动到栈顶
Ÿ Android 系统在运行多个进程时,若是系统资源不足,会强制结束一些进程。优先选择哪一个进程来结束是有优先级的。如下顺序靠上的优先结束
空:进程中全部 Activity 都已销毁
后台:进程中有一个中止状态的 Activity
可见:进程中有一个暂停状态的 Activity
前台:进程中正在运行一个 Activity
Ÿ 定义类继承 BroadcastReceiver ,重写 onReceive 方法
Ÿ 清单文件中声明<receiver>,须要在其中配置<intent-filter>指定接收广播的动做
Ÿ 当接收到匹配广播以后就会执行 onReceive 方法
Ÿ BroadcastReceiver 除了在清单文件中声明,也能够在代码中声明,使用 registerReceiver方法注册 Receiver
Ø 无序广播
Ÿ 使用sendBroadcast方法发送
Ÿ 被全部广播接收者接收,无序,不可中断
Ÿ 广播时可设置接收者权限,仅当接收者含有权限才能接收
Ÿ 接收者的<receiver>也可设置发送方权限,只接收含有权限应用的广播
Ø 有序广播
Ÿ 使用sendOrderedBroadcast方法发送
Ÿ 接收者能够在<intent-filter>中定义android:priority定义优先级,数字越大优先级越高
Ÿ 被各个广播接收者逐个接收,中途能够中断或者添加数据
abortBroadcast()
getResultExtras( true ).putString( "data" , " 新增数据 " );
Ÿ Android 系统在收到短信的时候会发送一条有序广播,咱们若是定义一个接收者接收这个广播,就能够获得短信内容,也能够拦截短信
Ÿ 定义广播接收者接收广播 android.provider.Telephony.SMS_RECEIVED
Ÿ 在 onReceive 方法内部调用 Intent 的 getExtras() 再调用 get(String) 获取其中 pdus 字段,获得一个 Object[],其中每个元素都是一个 byte[]
Ÿ 经过SmsMessage类的createFromPdu方法建立 SmsMessage 对象
Ÿ 从 SmsMessage 对象中便可获取发送者号码、短信内容、发送时间等信息
Ÿ 须要接收短信权限: < uses-permission android:name ="android.permission.RECEIVE_SMS" />
Ÿ Android 系统中收到短信的通知是一个有序通知,咱们如需拦截垃圾短信,能够配置较高的 priority,收到信息进行判断是否abortBroadcast()
Ÿ 定义广播接收者接收 android.intent.action.NEW_OUTGOING_CALL
Ÿ 须要权限 < uses-permission android:name = "android.permission.PROCESS_OUTGOING_CALLS" />
Ÿ 在 onReceive 方法中使用 getResultData() 和 setResultData() 方法获取和设置电话号码
Ÿ 广播接收者的生命周期是很是短暂的,在接收到广播的时候建立, onReceive() 方法结束以后销毁
Ÿ 广播接收者中不要作一些耗时的工做,不然会弹出 Application No Response 错误对话框
Ÿ 最好也不要在广播接收者中建立子线程作耗时的工做,由于广播接收者被销毁后进程就成为了空进程,很容易被系统杀掉
Ÿ 耗时的较长的工做最好放在服务中完成
Ÿ Service 是一种在后台运行,没有界面的组件,由其余组件调用开始。
Ÿ 建立 Service ,定义类继承 Service , AndroidManifest.xml 中定义 <service>
Ÿ 开启 Service ,在其余组件中调用 startService方法
Ÿ 中止 Service ,调用 stopService方法
须要权限: android.permission.READ_PHONE_STATE
TelephonyManager manager = (TelephonyManager) getSystemService( TELEPHONY_SERVICE );
manager.listen( new MyListener(), PhoneStateListener. LISTEN_CALL_STATE );
private final class MyListener extends PhoneStateListener {
private String num ;
private MediaRecorder recorder ;
public void onCallStateChanged( int state, String incomingNumber) {
switch (state) {
case TelephonyManager. CALL_STATE_RINGING :
num = incomingNumber;
break ;
case TelephonyManager. CALL_STATE_OFFHOOK :
try {
File file = new File(Environment.getExternalStorageDirectory(), num + "_" + System.currentTimeMillis() + ".3gp" );
recorder = new MediaRecorder();
recorder .setAudioSource(AudioSource. MIC );
recorder .setOutputFormat(OutputFormat. THREE_GPP );
recorder .setAudioEncoder(AudioEncoder. AMR_NB );
recorder .setOutputFile( file .getAbsolutePath());
recorder .prepare();
recorder .start();
} catch (Exception e) {
e.printStackTrace();
}
break ;
case TelephonyManager. CALL_STATE_IDLE :
if ( recorder != null ) {
recorder .stop();
recorder .release();
}
break ;
}
}
}
Ÿ 使用bindService绑定服务,传入一个自定义的ServiceConnection用来接收 IBinder
Ÿ 定义一个业务接口,其中定义须要的使用的方法
Ÿ 服务中自定义一个 IBinder 继承 Binder 并实现业务接口,在 onBind方法中返回
Ÿ 调用端将 IBinder 转为接口类型,调用接口中的方法便可调用到服务中的方法
Ÿ 远程绑定服务时没法经过同一个接口来调用方法,这时就须要使用 AIDL 技术
Ÿ 将接口扩展名改成“.aidl”
Ÿ 去掉权限修饰符
Ÿ gen 文件夹下会生成同名接口
Ÿ 将服务中自定义的 IBinder 类改成继承接口中的 S tub
Ÿ ServiceConnection中返回的 IBinder 是代理对象,不能使用强转,改用 S tub.asInterface()
Ÿ AIDL 默认只能使用 Java 中基本数据类型和 String 、 List 、 Map , List 和 Map 中的元素类型也只能是这些类型。
Ÿ 若是须要使用其余类型数据,使用的类必须实现 Parcelable 接口以完成序列化和反序列化工做
重写 public void writeToParcel(Parcel dest, int flags)
定义 public static final Parcelable.Creator<Person> CREATOR
Ÿ 定义该类对应的 AIDL
package 包名
parcelable 类名
Ÿ 在接口 AIDL 中导入该类,注意:即便是同一个包也须要导入
screenSV .getHolder().setType(SurfaceHolder. SURFACE_TYPE_PUSH_BUFFERS ); // 设置缓冲区数据
screenSV .getHolder().setKeepScreenOn( true ); // 设置屏幕保持
screenSV .getHolder().addCallback( new MyCallback()); // 设置回调函数
player .reset();
player .setDisplay( screenSV .getHolder()); // 设置显式
player .setDataSource( "/mnt/sdcard/1.mp4" ); // 设置数据源
player .prepare(); // 准备
player .seekTo(position); // 跳转到指定位置
player .start();
Ÿ 须要权限
< uses-permission android:name = "android.permission.CAMERA" />
Ÿ 打开摄像头
Camera.open()
SDK2.3 以后支持前置摄像头, open 方法能够接收一个 int 参数,用来指定哪一个摄像头
Ÿ 设置预览显示位置
setPreviewDisplay(SurfaceHolder holder)
注意 SurfaceView 不在前端显示的时候会被销毁,恢复以后会重绘
Ÿ 开始预览
startPreview()
将摄像头拍摄画面显示在 SurfaceView 中,在此以前可对摄像头进行参数配置
getParameters() 方法能够获取摄像头的相关参数Parameters,调用其内部方法便可进行配置
Ÿ 自动对焦
autoFocus(AutoFocusCallback cb)
自动对焦是一个异步操做,若是咱们向等待自动对焦结束以后才开始拍照,须要传入一个回调对象,在其回调函数中调用拍照方法
Ÿ 拍照
takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback jpeg)
拍照也是异步操做,须要经过回调函数来获得拍照以后的数据
注意拍照以后摄像头不回自动回到预览状态,须要重写调用startPreview()方法
Ÿ 须要权限
< uses-permission android:name = "android.permission.RECORD_AUDIO" />
< uses-permission android:name = "android.permission.CAMERA" />
Ÿ 建立MediaRecorder
new MediaRecorder()
Ÿ 设置音频输入源
setAudioSource( int audio_source)
Ÿ 设置视频输入源
setVideoSource( int video_source)
Ÿ 设置输出格式
setOutputFormat( int output_format)
Ÿ 设置音频编码器
setAudioEncoder( int audio_encoder)
Ÿ 设置视频编码器
setVideoEncoder( int video_encoder)
Ÿ 设置预览显示位置
setPreviewDisplay(Surface sv)
Ÿ 设置输出文件
setOutputFile(String path)
Ÿ 准备录制
prepare()
Ÿ 开始录制
start()
开始录制以前须要结束摄像头的预览
Ÿ 结束录制释放资源
stop()
release()
Ÿ 建立通知
Toast.makeText(Context context, CharSequence text, int duration)
Toast.makeText(Context context, int resId, int duration)
Ÿ 发送通知
show()
Ÿ 获取系统通知服务
NotificationManager nm = (NotificationManager) getSystemService( NOTIFICATION_SERVICE )
Ÿ 建立通知
经过构造函数建立 : Notification( int icon, CharSequence tickerText, long when)
icon: 通知的图片资源 ID
tickerText: 状态栏中显示的消息内容
when: 时间
Ÿ 建立PendingIntent以供点击时发送
PendingIntent.getActivity(Context context, int requestCode, Intent intent, int flags)
context: 当前上下文
requestCode: 请求码
intent: 点击时要发送的意图
flags: 类型 , PendingIntent中提供了常量选择
Ÿ 设置通知点击事件
调用Notification 对象方法 : setLatestEventInfo(Context context, CharSequence contentTitle, CharSequence contentText, PendingIntent contentIntent)
context: 当前上下文
contentTitle: 标题
contentText: 内容
contentIntent: 点击时触发的意图
Ÿ 设置通知点击后清除
设置Notification 对象属性 n. flags = Notification. FLAG_AUTO_CANCEL ;
Ÿ 发送消息
调用Notification对象方法 : notify( int id, Notification notification)
Ø 普通对话框
new AlertDialog.Builder( this ) //
.setTitle( " 普通对话框 " ) //
.setMessage( " 普通内容 " ) //
.setCancelable( false ) //
.setPositiveButton( "YES" , listener) // listener 为 OnClickListener 监听器对象 , 监听按钮被选中
.setNeutralButton( "CANCEL" , listener) //
.setNegativeButton( "NO" , listener) //
.show();
Ø 列表对话框
new AlertDialog.Builder( this ) //
.setTitle( " 列表对话框 " ) //
.setCancelable( false ) //
.setItems( items , listener) // listener 为 OnClickListener 监听器对象 , 监听列表项被选中
.show();
Ø 单选对话框
new AlertDialog.Builder( this ) //
.setTitle( " 单选对话框 " ) //
.setCancelable( false ) //
.setSingleChoiceItems( items , 0, choiceLinstener) // 0, 为默认选中索引 , choiceLinstener 为 OnClickListener 监听器对象 , 监听单选按钮被选中
.setPositiveButton( " 肯定 " , positiveLinstener) // positiveLinstener 为 OnClickListener 监听器对象 , 监听肯定按钮点击
.show();
Ø 多选对话框
new AlertDialog.Builder( this ) //
.setTitle( " 多选对话框 " ) //
.setCancelable( false ) //
.setMultiChoiceItems( items , checkedArr, choiceListener) // checkedArr 为默认选中 , choiceListener 为 OnMultiChoiceClickListener 监听器对象 , 监听多选按钮被选中
.setPositiveButton( " 肯定 " , positiveLinstener) // positiveLinstener 为 OnClickListener 监听器对象 , 监听肯定按钮点击
.show();
Ø 进度对话框
ProgressDialog dialog = new ProgressDialog( this );
dialog.setProgressStyle(ProgressDialog. STYLE_HORIZONTAL ); // 设置进度条样式
dialog.setTitle( " 下载中 " );
dialog.setMessage( " 请稍候 ..." );
dialog.setCancelable( false );
dialog.setMax(100);
dialog.show();
dialog.setProgress(10); // 设置进度
dialog.dismiss(); // 对话框结束
关于通知的文档位置: android-sdk-windows/docs/guide/topics/ui/notifiers/index.html
Ø XML 配置
Ÿ 在主界面中配置 <ListView> 标签
Ÿ 在 res/layout/ 文件夹下建立一个新的 xml 文件指定每一个条目的布局
Ø Java 代码构建 ListView
Ÿ 获取 ListView 对象
Ÿ 设置一个 Adapter
BaseAdapter :实现内部抽象方法
SimpleAdapter:以 List<Map<String, ?>> 形式封装数据
SimpleCursorAdapter:以 Cursor 对象封装数据, Cursor 中须要有“ _id ”一列
Ÿ 添加 OnItemClickListener
调用 ListView 的 getItemAtPosition(int) 方法能够获取封装数据的容器
若是传入的是 BaseAdapter ,获取到的就是咱们自定义方法中返回的内容
若是传入的是SimpleAdapter,获取到的就是一个 Map<String, ?>
若是传入的是SimpleCursorAdapter,得到到的就是一个 Cursor ,而且 Cursor 以指向选中的一条记录
Ÿ 定义 <RadioGroup>
Ÿ 在 <RadioGroup> 中定义 <RadioButton> 和 <Button>
Ÿ 处理 Button 的点击事件
Ÿ 根据 ID 获取 RadioGroup 对象,调用其 getCheckedRadioButtonId()方法能够获取其中被选中的RadioGroup 的 ID
Ø 代码
< RadioGroup
android:id = "@+id/lessonsRG"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:orientation = "horizontal" >
< RadioButton
android:id = "@+id/javaRB"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = "Java" />
< RadioButton
android:id = "@+id/netRB"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = ".Net" />
< RadioButton
android:id = "@+id/phpRB"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = "PHP" />
< Button
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:onClick = " onR radioClick"
android:text = " 肯定 " />
</ RadioGroup >
public void onRradioClick(View view) {
RadioGroup lessonRG = (RadioGroup) findViewById(R.id. lesson s RG );
int id = lessonRG.getCheckedRadioButtonId(); // 获取选中的 id
String msg = null ;
switch (id) {
case R.id. javaRB :
msg = "Java" ;
break ;
case R.id. netRB :
msg = ".Net" ;
break ;
case R.id. phpRB :
msg = "PHP" ;
break ;
}
Toast.makeText( this , msg, 0).show();
}
Ÿ 定义若干 <CheckBox> 和一个 <Button>
Ÿ 处理 Button 的点击事件
Ÿ 根据 ID 获取每一个 CheckBox ,调用其 isChecked()方法判断是否被选中
Ø 代码
< LinearLayout
android:layout_width = "fill_parent"
android:layout_height = "wrap_content" >
< CheckBox
android:id = "@+id/javaCB"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = "Java" />
< CheckBox
android:id = "@+id/netCB"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = ".Net" />
< CheckBox
android:id = "@+id/phpCB"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:text = "PHP" />
< Button
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:layout_weight = "1"
android:onClick = "checkboxOnClick"
android:text = " 肯定 " />
</ LinearLayout >
public void checkboxOnClick(View view) {
CheckBox javaCB = (CheckBox) findViewById(R.id. javaCB );
CheckBox netCB = (CheckBox) findViewById(R.id. netCB );
CheckBox phpCB = (CheckBox) findViewById(R.id. phpCB );
StringBuilder sb = new StringBuilder();
sb.append(javaCB.isChecked() ? javaCB.getText() + " " : "" );
sb.append(netCB.isChecked() ? netCB.getText() + " " : "" );
sb.append(phpCB.isChecked() ? phpCB.getText() + " " : "" );
Toast.makeText( this , sb, 0).show();
}
Ÿ 定义 <Spinner> 标签
Ÿ 建立一个适配器
Ÿ 获取 Spinner 标签,调用 setAdapter(SpinnerAdapter adapter)方法设置一个适配器
Ÿ 调用setOnItemSelectedListener(OnItemSelectedListener listener)方法设置监听器监听选中事件
Ø XML 配置
< Spinner
android:id = "@+id/spinner"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content" />
Ø 使用字符串构建适配器
private void setSpinnerByString() {
final Spinner spinner = (Spinner) findViewById(R.id. spinner );
ArrayAdapter<String> adapter = new ArrayAdapter<String>( this , android.R.layout. simple_spinner_item ); // 设置样式
adapter.setDropDownViewResource(android.R.layout. simple_spinner_dropdown_item ); // 设置下拉后样式
adapter.add( "Java" );
adapter.add( ".Net" );
adapter.add( "PHP" );
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener( new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selection = (String) spinner.getItemAtPosition(position);
Toast.makeText(getApplicationContext(), selection, 0).show();
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Ø 使用 JavaBean 构建适配器
private void setSpinnerByJavaBean() {
final Spinner spinner = (Spinner) findViewById(R.id. spinner );
ArrayAdapter<User> adapter = new ArrayAdapter<User>( this , android.R.layout. simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout. simple_spinner_dropdown_item );
adapter.add( new User(1, "lhm" , "lhm@itcast.cn" ));
adapter.add( new User(2, "yzk" , "yzk@itcast.cn" ));
adapter.add( new User(3, "hsp" , "hsp@itcast.cn" ));
spinner .setAdapter(adapter);
spinner .setOnItemSelectedListener( new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
User selection = (User) spinner .getItemAtPosition(position);
Toast.makeText(getApplicationContext(), selection.getName(), 0).show();
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Ø 使用资源文件构建适配器
< string-array name = "items" >
< item > Java </ item >
< item > .Net </ item >
< item > PHP </ item >
</ string-array >
private void setSpinnerByResource() {
final Spinner spinner = (Spinner) findViewById(R.id. spinner );
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( this , R.array. items , android.R.layout. simple_spinner_item );
adapter.setDropDownViewResource(android.R.layout. simple_spinner_dropdown_item );
spinner .setAdapter(adapter);
spinner .setOnItemSelectedListener( new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
CharSequence selection = (CharSequence) spinner .getItemAtPosition(position);
Toast.makeText(getApplicationContext(), selection, 0).show();
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Ø 自定义适配器样式
<? xml version = "1.0" encoding = "utf-8" ?>
< LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
android:orientation = "horizontal" >
< ImageView
android:layout_width = "50dp"
android:layout_height = "50dp"
android:src = "@android:drawable/ic_delete" />
< TextView
android:id = "@+id/content"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:textSize = "50sp" />
</ LinearLayout >
private void setSpinnerByCustom() {
final Spinner spinner = (Spinner) findViewById(R.id. spinner );
ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>( this , R.layout. item , R.id. content );
adapter.add( "Java" );
adapter.add( ".Net" );
adapter.add( "PHP" );
spinner .setAdapter(adapter);
spinner .setOnItemSelectedListener( new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String selection = (String) spinner .getItemAtPosition(position);
Toast.makeText(getApplicationContext(), selection, 0).show();
}
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Ø 添加菜单项
Ÿ 重写 Actvity 的 onCreateOptionsMenu(Menu menu)方法
Ÿ 添加菜单项
调用方法中参数 menu 的 add(CharSequence title) 方法
Ÿ 添加子菜单
调用 menu 对象的 addSubMenu( final CharSequence title)
该方法返回一个SubMenu对象
Ÿ 添加子菜单的菜单项
调用SubMenu对象的add(CharSequence title) 方法
Ø 处理菜单点击事件
Ÿ 重写 Activity 的 onOptionsItemSelected(MenuItem item) 方法
参数 item 即为被选中的菜单项
Ø 代码
public boolean onCreateOptionsMenu(Menu menu) {
menu.add( " 增长 " );
menu.add( " 修改 " );
menu.add( " 删除 " );
SubMenu subMenu = menu.addSubMenu( " 查询 " );
subMenu.add( " 按照序号查询 " );
subMenu.add( " 按照姓名查询 " );
subMenu.add( " 按照邮箱查询 " );
return super .onCreateOptionsMenu(menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText( this , item.getTitle(), 0).show();
return super .onOptionsItemSelected(item);
}
Ø 单次提示
Ø 代码
< AutoCompleteTextView
android:id = "@+id/actv"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:completionThreshold = "1" />
private void setAutoCompleteTextView() {
AutoCompleteTextView actv = (AutoCompleteTextView) findViewById(R.id. actv );
String[] items = { "tom" , "tony" , "terry" , " 张孝祥 " , " 张海军 " , " 张泽华 " };
ArrayAdapter<String> adapter = new ArrayAdapter<String>( this , android.R.layout. simple_dropdown_item_1line , items);
actv.setAdapter(adapter);
}
Ø 屡次提示
Ø 代码
< MultiAutoCompleteTextView
android:id = "@+id/mactv"
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:completionThreshold = "1" />
private void setMultiAutoCompleteTextView() {
MultiAutoCompleteTextView mactv = (MultiAutoCompleteTextView) findViewById(R.id. mactv );
String[] items = { "tom" , "tony" , "terry" , " 张孝祥 " , " 张海军 " , " 张泽华 " };
ArrayAdapter<String> adapter = new ArrayAdapter<String>( this , android.R.layout. simple_dropdown_item_1line , items);
mactv.setAdapter(adapter);
mactv.setTokenizer( new MultiAutoCompleteTextView.CommaTokenizer());
}
Ø 建立手势库
Ÿ 导入 SDK 中的工程
android-sdk-windows\samples\android-8\GestureBuilder
这个工程不能直接导入,须要添加三个配置文件:.classpath、.project、default.properties
Ÿ 将工程部署到手机中,建立手势库
手势库会存储在手机 SD 卡的根目录,文件名为: gestures
Ø 代码
将gestures放入 res/raw 文件夹下
< android.gesture.GestureOverlayView
android:id = "@+id/gov"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:gestureStrokeType = "multiple" />
GestureOverlayView gov = (GestureOverlayView) findViewById(R.id. gov );
final GestureLibrary library = GestureLibraries.fromRawResource( this , R.raw. gestures );
library.load();
gov.addOnGesturePerformedListener( new OnGesturePerformedListener() {
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> list = library.recognize(gesture);
for (Prediction p : list)
System. out .println(p. name + ": " + p. score );
}
});
Ø 代码
< WebView
android:id = "@+id/webView"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" />
WebView webView = (WebView) findViewById(R.id. webView );
webView.getSettings().setBuiltInZoomControls( true ); // 放大缩小按钮
webView.getSettings().setJavaScriptEnabled( true ); // JS 容许
webView.setWebChromeClient( new WebChromeClient()); // Chrome 内核
webView.loadUrl( "http://192.168.1.10 0 :8080" );
Ø 定义样式
Ÿ 设置样式,在 values 文件夹下的任意文件中的 <resources>中配置 <style> 标签
< style name = " style 1" >
< item name = "android:layout_width" > fill_parent </ item >
< item name = "android:layout_height" > wrap_content </ item >
</ style >
Ÿ 继承样式,在 <style> 标签中配置属性 parent
< style name = " style2 " parent = "@style/ style 1" >
< item name = "android:textColor" > #FF0000 </ item >
</ style >
Ÿ 继承样式,在 name 中引用其余样式
< style name = " style 2. style 3" >
< item name = "android:textSize" > 30sp </ item >
</ style >
Ø 使用样式
Ÿ 在 layout 文件的标签中配置 style 属性
< Button
style = "@style/ style2.style3 "
android:text = " 这是 一个按钮 "
/>
Ÿ 定义过的样式也能够应用在 <activity> 和 <application> 标签中,使用 theme属性尽心配置
< style name = "theme" >
< item name = "android:windowNoTitle" > true </ item >
< item name = "android:windowFullscreen" > ?android:windowNoTitle </ item >
</ style >
< activity android:name = ".MainActivity"
android:label = "@string/app_name"
android:theme = "@style/theme"
>
Ÿ ? 表示引用其余属性的值
Ÿ @ 表示访问资源文件
Ÿ 若是使用 android 内置的样式, IDE 自动提示的“ _ ”要替换成“ . ”
Ÿ 在 values 和 drawable 文件夹后加上语言以及地区名,程序中须要国际化的部分使用资源 ID
values-en-rUK
values-en-rUS
values-zh-rCN
values-zh-rTW
Ÿ 匹配规则
在匹配资源时先会找语言、地区彻底匹配的
若是没有地区匹配的,则查找语言匹配的
若是没有语言匹配的则找默认 values
Ÿ 在 layout 文件夹后加上分辨率,系统会根据屏幕尺寸自动选择
注意分辨率中的乘号是“ x ”不是“ * ”
Ÿ 若是没有匹配的分辨率会找默认 layout 文件夹
Ÿ 经过多个画面连续播放实现动画效果
Ÿ 详见文档 android-sdk-windows/docs/guide/topics/resources/animation-resource.html
Ÿ 将某个组件以渐变的方式实现透明、缩放、移动、旋转等动画效果
Ÿ 详见文档 android-sdk-windows/docs/guide/topics/resources/animation-resource.html
Ÿ 在 startActivity() 方法调用以后调用 overridePendingTransition( int enterAnim, int exitAnim)方法
enterAnim 进入的动画资源 id
exitAnim 退出的动画 资源 id
Ÿ XML 配置
< ViewFlipper
android:id = "@+id/viewFlipper"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
>
< ImageView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:src = "@drawable/bb2"
/>
< ImageView
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:src = "@drawable/bb3"
/>
</ ViewFlipper >
Ÿ Java 代码
public boolean onTouchEvent(MotionEvent event) {
ViewFlipper viewFlipper = (ViewFlipper) findViewById(R.id. viewFlipper );
switch (event.getAction()) {
case MotionEvent. ACTION_DOWN :
start = event.getX();
break ;
case MotionEvent. ACTION_UP :
float end = event.getX();
if (end > start ) {
viewFlipper .setInAnimation( this , R.anim. previous_enter );
viewFlipper .setOutAnimation( this , R.anim. previous_exit );
viewFlipper .showPrevious();
} else if (end < start ) {
viewFlipper .setInAnimation( this , R.anim. next_enter );
viewFlipper .setOutAnimation( this , R.anim. next_exit );
viewFlipper .showNext();
}
break ;
}
return super .onTouchEvent(event);
}
Ø 传感器参数
Ÿ 传感器类型
方向 Sensor. TYPE_ORIENTATION
加速 Sensor. TYPE_ACCELEROMETER
光线 Sensor. TYPE_LIGHT
磁场 Sensor. TYPE_MAGNETIC_FIELD
距离 Sensor. TYPE_PROXIMITY
温度 Sensor. TYPE_TEMPERATURE
Ÿ 传感器反应速度
SensorManager. SENSOR_DELAY_FASTEST
SensorManager. SENSOR_DELAY_GAME
SensorManager. SENSOR_DELAY_UI
SensorManager. SENSOR_DELAY_NORMAL
Ø 使用方向传感器
Ÿ 得到传感器管理器
SensorManager manager = (SensorManager) getSystemService( SENSOR_SERVICE );
Ÿ 得到方向传感器
Sensor sensor = manager.getDefaultSensor(Sensor. TYPE_ORIENTATION );
Ÿ 注册监听器
manager .registerListener( listener , sensor , SensorManager. SENSOR_DELAY_NORMAL );
Ÿ 监听器
private final class MySensorEventListener implements SensorEventListener {
public void onSensorChanged(SensorEvent event) {
System. out .println(event. values [0]);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
Ÿ 取消监听器
manager .unregisterListener( listener , sensor );
Ø 拖拽
Ÿ XML 配置
< ImageView
android:id = "@+id/image"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:scaleType = "matrix"
android:src = "@drawable/image" />
Ÿ Java代码
ImageView imageView = (ImageView) findViewById(R.id. image );
imageView.setOnTouchListener( new MyOnTouchListener());
private class MyOnTouchListener implements OnTouchListener {
private float x ;
private float y ;
private Matrix currentMatrix = new Matrix(); // 用来操做图片的矩阵
private Matrix oldMatrix = new Matrix();
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent. ACTION_DOWN : // 按下时
x = event.getX(); // 获取 x 轴坐标
y = event.getY(); // 获取 y 轴坐标
oldMatrix .set( imageView .getImageMatrix()); // 记住位置
break ;
case MotionEvent. ACTION_MOVE : // 移动时
currentMatrix .set( oldMatrix ); // 设置成按下时记住的位置
currentMatrix .postTranslate(event.getX() - x , event.getY() - y ); // 改变位置
break ;
}
imageView .setImageMatrix( currentMatrix ); // 移动图片
return true ;
}
}
Ø 多点触摸
private class MyOnTouchListener implements OnTouchListener {
private float x ; // 图片移动前的 x 轴坐标
private float y ; // 图片移动前的 y 轴坐标
private Matrix currentMatrix = new Matrix(); // 用来移动图片的矩阵
private Matrix oldMatrix = new Matrix(); // 图片移动前的矩阵
private int type ; // 操做类型 , 一根手指触摸仍是两根手指触摸
private float start ; // 第二根手指按下时的距离
private float end ; // 两根手指移动后的距离
private PointF point ; // 放大时的中心点
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction() & MotionEvent. ACTION_MASK ) {
case MotionEvent. ACTION_DOWN :
type = 1;
x = event.getX();
y = event.getY();
oldMatrix .set( imageView .getImageMatrix());
break ;
case MotionEvent. ACTION_MOVE :
currentMatrix .set( oldMatrix );
if ( type == 1) { // 1 根手指触摸
currentMatrix .postTranslate(event.getX() - x , event.getY() - y );
} else { // 2 跟手指触摸
end = countDistance(event); // 计算结束时距离
float scale = end / start ; // 计算缩放比例
currentMatrix .postScale(scale, scale, point . x , point . y ); // 设置缩放
}
break ;
case MotionEvent. ACTION_POINTER_DOWN :
type = 2;
start = countDistance(event); // 计算开始时距离
point = countPoint(event); // 计算中心点
oldMatrix .set( imageView .getImageMatrix());
break ;
}
imageView .setImageMatrix( currentMatrix ); // 改变图片
return true ;
}
}
public float countDistance(MotionEvent event) {
float a = event.getX(1) - event.getX(0); // x 轴距离
float b = event.getY(1) - event.getY(0); // y 轴距离
return ( float ) Math.sqrt(a * a + b * b); // 勾股定理
}
public PointF countPoint(MotionEvent event) {
float x = (event.getX(0) + event.getX(1)) / 2; // x 轴中间点
float y = (event.getY(0) + event.getY(1)) / 2; // y 轴中间点
return new PointF(x, y);
}
Ø 电话号码、运营商信息
Ÿ 须要权限
< uses-permission android:name = "android.permission.READ_PHONE_STATE" />
< uses-permission android:name = "android.permission.ACCESS_COARSE_LOCATION" />
Ÿ Java 代码
TelephonyManager manager = (TelephonyManager) getContext().getSystemService(Context. TELEPHONY_SERVICE );
System. out .println( " 电话号码 : " + manager.getLine1Number());
System. out .println( " 运营商编号 : " + manager.getNetworkOperator());
System. out .println( " 运营商名字 : " + manager.getNetworkOperatorName());
Ø 联系人
Ÿ 须要权限
< uses-permission android:name = "android.permission.READ_ CONTACTS " />
< uses-permission android:name = "android.permission. WRITE _ CONTACTS " />
Ÿ Java 代码
Uri uri = Uri.parse( "content://icc/adn" );
Cursor c = getContentResolver().query(uri, null , null , null , null );
while (c.moveToNext())
System. out .println(c.getString(c.getColumnIndex( "name" )) + ": " + c.getString(c.getColumnIndex( "number" )));
Ø 通话记录
Ÿ 须要权限
< uses-permission android:name = "android.permission.READ_ CONTACTS " />
< uses-permission android:name = "android.permission. WRITE _ CONTACTS " />
Ÿ Java 代码
Uri uri = CallLog.Calls. CONTENT_URI ;
Cursor c = getContentResolver().query(uri, null , null , null , null );
while (c.moveToNext())
System. out .println(c.getString(c.getColumnIndex( "number" )) + ": " + c.getString(c.getColumnIndex( "type" )));
Ÿ 源代码
ContactsProvider\src\com\android\providers\contacts\ CallLogProvider.java
Ÿ 须要权限
< uses-permission android:name = "android.permission. INSTALL_PACKAGES " />
Ÿ Java 代码
File file = new File(Environment.getExternalStorageDirectory(), " test .apk" );
Intent intent = new Intent();
intent.setAction(Intent. ACTION_VIEW );
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive" );
startActivity(intent);
Ÿ 杀死当前进程
Process.killProcess(Process.myPid());
Ÿ 退出虚拟机
System.exit(0);
Ÿ 根据包名关闭后台进程
ActivityManager manager = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
manager.restartPackage( "cn.itcast.test" );
< uses-permission android:name = "android.permission.RESTART_PACKAGES" />
Ÿ HTML
<! DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=UTF-8" >
< title > Insert title here </ title >
< script type = "text/javascript" >
function show(jsondata) {
var jsonobjs = eval(jsondata);
var table = document.getElementById( "personTable" );
for ( var y = 0; y < jsonobjs.length; y++) {
var tr = table.insertRow(table.rows.length);
var td1 = tr.insertCell(0);
var td2 = tr.insertCell(1);
td2.align = "center" ;
var td3 = tr.insertCell(2);
td3.align = "center" ;
td1.innerHTML = jsonobjs[y].name;
td2.innerHTML = jsonobjs[y].amount;
td3.innerHTML = "<a href='javascript:contact.call(\"" + jsonobjs[y].phone + "\")'>" + jsonobjs[y].phone + "</a>" ;
}
}
</ script >
</ head >
< body onload = "javascript:contact.show C ontacts()" >
< table border = "0" width = "100%" id = "personTable" cellspacing = "0" >
< tr >
< td width = "30%" > 姓名 </ td >
< td width = "30%" align = "center" > 存款 </ td >
< td align = "center" > 电话 </ td >
</ tr >
</ table >
</ body >
</ html >
Ÿ XML 代码
< WebView
android:id = "@+id/webView"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" />
Ÿ Java 代码
public class MainActivity extends Activity {
private WebView webView ;
public void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout. main );
webView = (WebView) findViewById(R.id. webView );
webView .getSettings().setJavaScriptEnabled( true );
webView .loadUrl( "file:///android_asset/index.html" );
webView .addJavascriptInterface( new Contact(), "contact" );
}
private final class Contact {
public void showContacts() {
String json = "[{\"name\":\"zxx\", \"amount\":\"99999\", \"phone\":\"18600012345\"}]" ;
webView .loadUrl( "javascript:show('" + json + "')" );
}
public void call(String phone) {
startActivity( new Intent(Intent. ACTION_CALL , Uri.parse( "tel:" + phone)));
}
}
}
Ÿ 使用解压缩工具打开 apk 文件,找到其中 dex 文件
Ÿ 建立 Java 工程,导入 dex2jar中的全部 jar 文件
Ÿ 建立运行环境运行其中pxb.android.dex2jar.v3.Main 类, 指定 dex 文件地址,会在同目录下生成 jar 文件