﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-&lt;font color="#FFFF00"&gt;金色闪电--陈彦虎（Ryan）&lt;/font&gt;-文章分类-Android</title><link>http://www.blogjava.net/kissyan4916/category/47135.html</link><description>哎哟 Orz，不错喔~~希望结识更多喜爱Java的朋友!&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;QQ：95350863 MSN：chenyanhubusiness@gmail.com   E-mail：chenyanhu@vip.163.com</description><language>zh-cn</language><lastBuildDate>Fri, 26 Aug 2011 01:24:04 GMT</lastBuildDate><pubDate>Fri, 26 Aug 2011 01:24:04 GMT</pubDate><ttl>60</ttl><item><title>Android游戏开发之数据库SQLite 详细介绍(转)</title><link>http://www.blogjava.net/kissyan4916/articles/357193.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Wed, 24 Aug 2011 07:15:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/357193.html</guid><description><![CDATA[<p>数据库SQLite介绍<br />&nbsp;&nbsp;&nbsp; <br />数据库最经典的四个操作 添加、删除、修改、查找，在处理大量数据的时候使用数据库可以帮我们迅速定位当前须要处理的数据，举个例子 好比现在要实现一个搜索功能 用数据库的话只须要其中一个搜索条件 一个数据库语句就可以迅速的在N条数据中找到我们需要的数据，如果不使用数据库那么查找起来会非常麻烦，效率大打折扣，所以在处理大量数据的时候使用数据库是明确的选择，在Android的开发中使用的数据库是SQLite ,它是一个轻量级的数据库 、非常小 、 移植性好、效率高、可靠 ，嵌入式设备因为受到硬件条件的限制所以非常适合使用 SQLite&nbsp; 数据库。</p>
<p><br />创建与删除数据库</p>
<p>封装一个类去继承SQLiteOpenHelper&nbsp; 在构造函数中传入数据库名称与数据库版本号，数据库被创建的时候会调用onCreate(SQLiteDatabase db) 方法，数据库版本号发生改变的时候会调用onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法，可以方便的对软件游戏升级后做出相应处理避免覆盖安装数据库发生改变产生的错误。调用SQLiteOpenHelper&nbsp; 的getReadableDatabase()方法去创建数据库，如果数据库不存在则创建 并且返回SQLiteDatabase对象，如果数据库存在则不创建只返回SQLiteDatabase对象。调用deleteDatabase(DATABASE_NAME)方法 传入数据库名称则可删除数据库。</p>
<p>&nbsp;<img alt="" src="http://www.blogjava.net/images/blogjava_net/kissyan4916/1.jpg" border="0" /><br /><br /></p>
<p>封装了一个DatabaseHelper类继承SQLiteOpenHelper 我使用了设计模式中的单例模式来处理这个类，这里说一下单例模式 单例模式是常见的代码设计模式之一 它的好处是在于避免在内存中频繁的实例化所以将它的对象写成static 静态 这样它的对象就只有一份存在静态内存区使用的时候只须要通过getInstance()就可以直接拿到这个静态对象。<br />&nbsp;<br />public class DatabaseHelper extends SQLiteOpenHelper {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; private static DatabaseHelper mInstance = null;&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /** 数据库名称 **/&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public static final String DATABASE_NAME = "xys.db";&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /** 数据库版本号 **/&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; private static final int DATABASE_VERSION = 1;&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**数据库SQL语句 添加一个表**/&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; private static final String NAME_TABLE_CREATE = "create table test("&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+"hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "number INTEGER);";&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; DatabaseHelper(Context context) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; super(context, DATABASE_NAME, null, DATABASE_VERSION);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; /**单例模式**/&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; static synchronized DatabaseHelper getInstance(Context context) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; if (mInstance == null) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mInstance = new DatabaseHelper(context);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; return mInstance;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public void onCreate(SQLiteDatabase db) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**向数据中添加表**/&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; db.execSQL(NAME_TABLE_CREATE);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**可以拿到当前数据库的版本信息 与之前数据库的版本信息&nbsp;&nbsp; 用来更新数据库**/&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * 删除数据库&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param context&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public boolean deleteDatabase(Context context) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; return context.deleteDatabase(DATABASE_NAME);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br /></p>
<p>在这个类中使用DatabaseHelper对象 实现创建与删除数据库、<br />&nbsp;<br />public class NewSQLite extends Activity {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; DatabaseHelper mDbHelper = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; SQLiteDatabase mDb = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Context mContext = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; protected void onCreate(Bundle savedInstanceState) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; setContentView(R.layout.create_sql);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mContext = this;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //创建DatabaseHelper对象&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDbHelper = DatabaseHelper.getInstance(mContext);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //调用getReadableDatabase方法如果数据库不存在 则创建&nbsp; 如果存在则打开&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDb= mDbHelper.getReadableDatabase();&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button0 = (Button)findViewById(R.id.createDateBase);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button0.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(NewSQLite.this, "成功创建数据库", Toast.LENGTH_LONG).show();&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button1 = (Button)findViewById(R.id.deleteDateBase);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button1.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDbHelper = DatabaseHelper.getInstance(mContext);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 调用getReadableDatabase方法如果数据库不存在 则创建 如果存在则打开&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDb = mDbHelper.getReadableDatabase();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 关闭数据库&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDbHelper.close();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 删除数据库&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDbHelper.deleteDatabase(mContext);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(NewSQLite.this, "成功删除数据库", Toast.LENGTH_LONG).show();&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; super.onCreate(savedInstanceState);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />}&nbsp; <br />创建的数据库会被保存在当前项目中 databases 路径下 具体如图所示</p>
<p><img alt="" src="http://www.blogjava.net/images/blogjava_net/kissyan4916/2.jpg" border="0" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>添加与删除数据库中的表</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数据库是可以由多张数据表组成的 如果添加一张数据库的表的话 可以使用 数据库语句 create table 名称(内容) 来进行添加 。这里给出一条创建数据库的语句 。 意思是创建一张表 名称为gameInfo 表中包含的字段 为&nbsp;&nbsp;&nbsp;&nbsp; _id&nbsp; 为INTEGER 类型 并且递增&nbsp; name 为Text类型&nbsp;&nbsp; hp mp 为INTEGER 默认数值为100 number 为INTEGER 类型。</p>
<p>&nbsp;<br />/**创建一张表的SQL语句**/&nbsp;&nbsp; <br />private static final String NAME_TABLE_CREATE = "create table gameInfo("&nbsp;&nbsp; <br />&nbsp;+ "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+ "hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"&nbsp;&nbsp; <br />&nbsp;+ "number INTEGER);";&nbsp; <br />数据库中删除一张表 直接使用DROP TABLE&nbsp; 表名称 就可以删除<br />&nbsp;<br />/**删除一张表的SQL语句**/&nbsp;&nbsp; <br />private static final String NAME_TABLE_DELETE = "DROP TABLE gameInfo";&nbsp; <br />在代码中去执行一条SQL语句 使用SQLiteDatabase对象去调用execSQL() 传入SQL语句就OK了。</p>
<p>&nbsp;<br />mDb.execSQL(NAME_TABLE_CREATE);&nbsp; </p>
<p><a href="http://www.linuxidc.com/Linux/2011-08/40540p2.htm"><img height="530" alt="" src="http://www.blogjava.net/images/blogjava_net/kissyan4916/3.jpg" width="373" border="0" /></a></p>
<p><br /></p>
<p>以创建一张名称为gameInfo的表为例 给出代码实现<br />&nbsp;<br />public class NewTable extends Activity {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; DatabaseHelper mDbHelper = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; SQLiteDatabase mDb = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Context mContext = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**创建一张表的SQL语句**/&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; private static final String NAME_TABLE_CREATE = "create table gameInfo("&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "_id INTEGER PRIMARY KEY AUTOINCREMENT," + "name TEXT,"+ "hp INTEGER DEFAULT 100,"+ "mp INTEGER DEFAULT 100,"&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + "number INTEGER);";&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**删除一张表的SQL语句**/&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; private static final String NAME_TABLE_DELETE = "DROP TABLE gameInfo";&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; protected void onCreate(Bundle savedInstanceState) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; setContentView(R.layout.create_table);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mContext = this;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDbHelper = DatabaseHelper.getInstance(mContext);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDb= mDbHelper.getReadableDatabase();&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button0 = (Button)findViewById(R.id.createTable);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button0.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDb.execSQL(NAME_TABLE_CREATE);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(NewTable.this, "成功添加数据表", Toast.LENGTH_LONG).show();&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(SQLiteException e) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(NewTable.this, "数据库中已存此表", Toast.LENGTH_LONG).show();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button1 = (Button)findViewById(R.id.deleteTable);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button1.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDb.execSQL(NAME_TABLE_DELETE);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(NewTable.this, "成功删除数据表", Toast.LENGTH_LONG).show();&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(SQLiteException e) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(NewTable.this, "数据库中已无此表", Toast.LENGTH_LONG).show();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; super.onCreate(savedInstanceState);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />}&nbsp; </p>
<p>&nbsp;</p>
<p>增加 删除 修改 查询 数据库中的数据</p>
<p>使用SQLiteDatabase对象调用 insert()方法 传入标的名称与ContentValues 添加的内容 则可以向数据库表中写入一条数据 delete ()为删除一条数据 update()为更新一条数据。 </p>
<p><br />我详细说一下查找一条数据使用的方法 query 中 跟了8个参数 </p>
<p>public Cursor query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy,String limit);</p>
<p>参数说明：</p>
<p>table:数据库表的名称</p>
<p>columns:数据库列名称数组 写入后最后返回的Cursor中只能查到这里的列的内容 </p>
<p><br />selection:查询条件 </p>
<p><br />selectionArgs:查询结果 </p>
<p>groupBy:分组列</p>
<p>having:分组条件</p>
<p>orderBy:排序列</p>
<p>limit:分页查询限制</p>
<p>Cursor:返回值，将查询到的结果都存在Cursor</p>
<p>Cursor是一个游标接口，每次查询的结果都会保存在Cursor中 可以通过遍历Cursor的方法拿到当前查询到的所有信息。</p>
<p>Cursor的方法</p>
<p>moveToFirst() //将Curor的游标移动到第一条<br />moveToLast()///将Curor的游标移动到最后一条<br />move(int offset)//将Curor的游标移动到指定ID<br />moveToNext()//将Curor的游标移动到下一条<br />moveToPrevious()//将Curor的游标移动到上一条<br />getCount() //得到Cursor 总记录条数<br />isFirst() //判断当前游标是否为第一条记录<br />isLast()//判断当前游标是否为最后一条数据<br />getInt(int columnIndex)&nbsp;&nbsp;&nbsp; //根据列名称获得列索引ID<br />getString(int columnIndex)//根据索引ID 拿到表中存的字段<br /><img alt="" src="http://www.blogjava.net/images/blogjava_net/kissyan4916/4.jpg" border="0" /><br /><br /></p>
<p>这里给出一个例子遍历Cursor的例子<br />&nbsp;<br />&nbsp;&nbsp; private void query(SQLiteDatabase db) {&nbsp;&nbsp; <br />// 把整张表的所有数据query到cursor中&nbsp;&nbsp;&nbsp; <br />Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null);&nbsp;&nbsp; <br />//判断cursor不为空 这个很重要&nbsp;&nbsp;&nbsp; <br />if (cursor != null) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 循环遍历cursor&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; while (cursor.moveToNext()) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 拿到每一行name 与hp的数值&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; String name = cursor.getString(cursor.getColumnIndex("name"));&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; String hp = cursor.getString(cursor.getColumnIndex("hp"));&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Log.v("info", "姓名是 " + name + "hp为 " + hp);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 关闭&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; cursor.close();&nbsp;&nbsp; <br />}&nbsp;&nbsp; <br />&nbsp;&nbsp; }&nbsp; </p>
<p><br />向大家推荐一个查看数据库的软件非常好用, 名称是SQLiteSpy.exe&nbsp; 如图所示 打开xys.db 文件 可以清晰的看见数据库表中储存的内容并且该软件支持执行SQL语句 可以直接在软件中操作，我给出这款软件的下载地址。看本文最后的下载地址</p>
<p><a href="http://www.linuxidc.com/Linux/2011-08/40540p3.htm"><img height="381" alt="" src="http://www.blogjava.net/images/blogjava_net/kissyan4916/5.jpg" width="717" border="0" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />&nbsp;<br />public class Newdate extends Activity {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; DatabaseHelper mDbHelper = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; SQLiteDatabase mDb = null;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Context mContext = null;&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /** 数据库字段 **/&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public final static String TABLE_NAME = "test";&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public final static String ID = "_id";&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public final static String NAME = "name";&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public final static String HP = "hp";&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public final static String MP = "mp";&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; protected void onCreate(Bundle savedInstanceState) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; setContentView(R.layout.create_date);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mContext = this;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 创建DatabaseHelper对象&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDbHelper = DatabaseHelper.getInstance(mContext);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 调用getReadableDatabase方法如果数据库不存在 则创建 如果存在则打开&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDb = mDbHelper.getReadableDatabase();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 初始化 给数据库表写入一些信息&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 10; i++) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insert(NAME, "雨松MOMO" + i);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 增加&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button0 = (Button) findViewById(R.id.add);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button0.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insert(NAME, "新添加小可爱");&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(Newdate.this, "添加一条数据名称为小可爱", Toast.LENGTH_LONG)&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .show();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 删除&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button1 = (Button) findViewById(R.id.delete);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button1.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete(ID, "1");&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(Newdate.this, "删除一条_id=1的数据", Toast.LENGTH_LONG)&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .show();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 修改&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button2 = (Button) findViewById(R.id.modify);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button2.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; update(NAME, "雨松MOMO3", "小可爱3");&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(Newdate.this, "更新名称雨松MOMO3 为小可爱3",&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.LENGTH_LONG).show();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; // 查找&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Button button3 = (Button) findViewById(R.id.find);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; button3.setOnClickListener(new OnClickListener() {&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onClick(View arg0) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cursor cursor = find(ID, "5");&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String name = cursor.getString(cursor.getColumnIndex(NAME));&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.makeText(Newdate.this, "查找ID为5数据的名称是 " + name,&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Toast.LENGTH_LONG).show();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; super.onCreate(savedInstanceState);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * 插入一条数据&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param key&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param date&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public void insert(String key, String date) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; ContentValues values = new ContentValues();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; values.put(key, date);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDb.insert(TABLE_NAME, null, values);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * 删除一掉数据&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param key&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param date&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public void delete(String key, String date) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDb.delete(TABLE_NAME, key + "=?", new String[] { date });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * 更新一条数据&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param key&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param oldDate&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param newDate&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public void update(String key, String oldDate, String newDate) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; ContentValues values = new ContentValues();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; values.put(key, newDate);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; mDb.update(TABLE_NAME, values, key + "=?", new String[] { oldDate });&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * 查找一条数据&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param key&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @param date&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; public Cursor find(String key, String date) {&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; Cursor cursor = mDb.query(TABLE_NAME, null, key + "=?",&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new String[] { date }, null, null, null);&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; if (cursor != null) {&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cursor.moveToFirst();&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; return cursor;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />&nbsp;&nbsp; <br />}&nbsp; <br />&nbsp;</p>
<p>最后如果你还是觉得我写的不够详细 看的不够爽 不要紧我把源代码的下载地址贴出来 </p>
<p>免费下载地址在 <a href="http://linux.linuxidc.com/">http://linux.linuxidc.com/</a></p>
<p>用户名与密码都是<a href="http://www.linuxidc.com">www.linuxidc.com</a></p>
<p>具体下载目录在 /2011年资料/Android入门教程/Android游戏开发之数据库SQLite 详细介绍/</p>
<p>本篇文章来源于 Linux公社网站(<a href="http://www.linuxidc.com">www.linuxidc.com</a>)&nbsp; 原文链接：<a href="http://www.linuxidc.com/Linux/2011-08/40540p3.htm">http://www.linuxidc.com/Linux/2011-08/40540p3.htm</a></p>
<p><a href="http://www.linuxidc.com/Linux/2011-08/40540p2.htm"></a>&nbsp;</p>
<p>&nbsp;</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/357193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2011-08-24 15:15 <a href="http://www.blogjava.net/kissyan4916/articles/357193.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android自适应屏幕方向和大小</title><link>http://www.blogjava.net/kissyan4916/articles/339702.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339702.html</guid><description><![CDATA[<p>一：不同的layout</p>
<p>Android手机 屏幕 大小不一，有480x320, 640x360, 800x480.怎样才能让App自动 适应不同的屏幕 呢？ <br />
&nbsp;&nbsp; 其实很简单，只需要在res目录下创建不同的layout文件 夹，比如layout-640x360,layout-800x480,所有的layout文件在编译 之后都会写入R.java里，而系统 会根据屏幕 的大小自己选择合适的layout进行使用。</p>
<p>二：hdpi、mdpi、ldpi</p>
<p>在之前的版本中，只有一个drawable，而2.1版本中有drawable-mdpi、drawable-ldpi、drawable-hdpi三个，这三个主要是为了支持多分辨率。</p>
<p>　　drawable- hdpi、drawable- mdpi、drawable-ldpi的区别：</p>
<p>　　(1)drawable-hdpi里面存放高分辨率的图片,如WVGA (480x800),FWVGA (480x854)</p>
<p>　　(2)drawable-mdpi里面存放中等分辨率的图片,如HVGA (320x480)</p>
<p>　　(3)drawable-ldpi里面存放低分辨率的图片,如QVGA (240x320)</p>
<p>　　系统会根据机器的分辨率来分别到这几个文件夹里面去找对应的图片。</p>
<p>　　在开发 程序 时为了兼容不同平台 不同屏幕 ，建议各自文件夹根据需求均存放不同版本图片。</p>
<p>屏幕 方向：</p>
<p>横屏竖屏自动切换：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 可以在res目录下建立layout-port和layout-land两个目录，里面分别放置竖屏和横屏两种布局文件，这样在手机屏幕 方向变化的时候系统会自动调用相应的布局文件，避免一种布局文件无法满足两种屏幕 显示的问题。</p>
<p>不切换：</p>
<p><br />
以下步骤是网上流传的，不过我自己之前是通过图形化界面 实现这个配置，算是殊途同归，有空我会把图片贴上来。</p>
<p>还要说明一点：每个activity 都有这个属性screenOrientation，每个activity都需要设置 ，可以设置为竖屏（portrait），也可以设置为无重力感应（nosensor）。</p>
<p>要让程序界面保持一个方向，不随手机方向转动而变化的处理办法： <br />
&nbsp; <br />
在AndroidManifest.xml里面配置一下就可以了。加入这一行android :screenOrientation="landscape"。<br />
例如（landscape是横向，portrait是纵向）：</p>
<p>代码 :</p>
<p>view plaincopy to clipboardprint?<br />
&lt;?xml version="1.0" encoding="utf-8"?&gt;&nbsp; <br />
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; package="com.ray.linkit"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:versionCode="1"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:versionName="1.0"&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;application android:icon="@drawable/icon" android:label="@string/app_name"&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".Main"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:label="@string/app_name"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:screenOrientation="portrait"&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;intent-filter&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action android:name="android.intent.action.MAIN" /&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.LAUNCHER" /&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/intent-filter&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/activity&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".GamePlay"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:screenOrientation="portrait"&gt;&lt;/activity&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".OptionView"&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:screenOrientation="portrait"&gt;&lt;/activity&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;/application&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp; &lt;uses-sdk android:minSdkVersion="3" /&gt;&nbsp; <br />
&lt;/manifest&gt;&nbsp; <br />
&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; package="com.ray.linkit"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:versionCode="1"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:versionName="1.0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;application android:icon="@drawable/icon" android:label="@string/app_name"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".Main"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:label="@string/app_name"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:screenOrientation="portrait"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;intent-filter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action android:name="android.intent.action.MAIN" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.LAUNCHER" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/intent-filter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/activity&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".GamePlay"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:screenOrientation="portrait"&gt;&lt;/activity&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".OptionView"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:screenOrientation="portrait"&gt;&lt;/activity&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/application&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;uses-sdk android:minSdkVersion="3" /&gt;<br />
&lt;/manifest&gt; </p>
<p>另外，android中每次屏幕 的切换动会重启Activity，所以应该在Activity销毁前保存当前活动的状态，在Activity再次Create的时候载入配置，那样，进行中的游戏 就不会自动重启了！</p>
<p>有的程序适合从竖屏切换到横屏，或者反过来，这个时候怎么办呢？可以在配置Activity的地方进行如下的配置android:screenOrientation="portrait"。这样就可以保证是竖屏总是竖屏了，或者landscape横向。</p>
<p>而有的程序是适合横竖屏切换的。如何处理呢？首先要在配置Activity的时候进行如下的配置：android:configChanges="keyboardHidden|orientation"，另外需要重写Activity的 onConfigurationChanged方法。实现方式如下，不需要做太多的内容：</p>
<p>view plaincopy to clipboardprint?<br />
@Override&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void onConfigurationChanged(Configuration newConfig) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onConfigurationChanged(newConfig);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // land do nothing is ok&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // port do nothing is ok&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/29/6043097.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:35 <a href="http://www.blogjava.net/kissyan4916/articles/339702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（二十） 双按事件捕获</title><link>http://www.blogjava.net/kissyan4916/articles/339701.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:34:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339701.html</guid><description><![CDATA[<p>对于游戏开发中我们可能经常要用到双按屏幕，在Android 1.6以前并没有提供完善的手势识别类，在Android 1.5 SDK中我们可以找到android.view.GestureDetector.OnDoubleTapListener，但是经过测试仍然无法正常工作，不知道什么原因，如果您知道可以联系android123@163.com 共享下。最终我们使用的解决方法如下 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 最终我们测试的如下:</p>
<p>view plaincopy to clipboardprint?<br />
public class TouchLayout extends RelativeLayout {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public Handler doubleTapHandler = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; protected long lastDown = -1;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public final static long DOUBLE_TIME = 500;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;public TouchLayout(Context context) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public TouchLayout(Context context, AttributeSet attrs) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public TouchLayout(Context context, AttributeSet attrs, int defStyle) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs, defStyle);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public boolean onTouchEvent(MotionEvent event) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.handleEvent(event);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event.getAction() == MotionEvent.ACTION_DOWN) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long nowDown = System.currentTimeMillis();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nowDown - lastDown &lt; DOUBLE_TIME)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (doubleTapHandler != null)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleTapHandler.sendEmptyMessage(-1);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastDown = nowDown;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; protected void handleEvent(MotionEvent event) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (event.getAction()) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case MotionEvent.ACTION_DOWN:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Do sth 这里处理即可&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case MotionEvent.ACTION_UP:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Do sth&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
}&nbsp; <br />
public class TouchLayout extends RelativeLayout {<br />
&nbsp;&nbsp;&nbsp; public Handler doubleTapHandler = null;<br />
&nbsp;&nbsp;&nbsp; protected long lastDown = -1;<br />
&nbsp;&nbsp;&nbsp; public final static long DOUBLE_TIME = 500;<br />
&nbsp;<br />
&nbsp;public TouchLayout(Context context) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public TouchLayout(Context context, AttributeSet attrs) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs);<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public TouchLayout(Context context, AttributeSet attrs, int defStyle) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs, defStyle);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public boolean onTouchEvent(MotionEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.handleEvent(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event.getAction() == MotionEvent.ACTION_DOWN) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long nowDown = System.currentTimeMillis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (nowDown - lastDown &lt; DOUBLE_TIME)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (doubleTapHandler != null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleTapHandler.sendEmptyMessage(-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastDown = nowDown;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; protected void handleEvent(MotionEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (event.getAction()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case MotionEvent.ACTION_DOWN:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Do sth 这里处理即可<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case MotionEvent.ACTION_UP:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Do sth<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; }<br />
} </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034698.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339701.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:34 <a href="http://www.blogjava.net/kissyan4916/articles/339701.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十八） SoundPool类 </title><link>http://www.blogjava.net/kissyan4916/articles/339699.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:33:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339699.html</guid><description><![CDATA[<p>对于Android的游戏音效播放，上次Android123已经告诉大家使用SoundPool类来实现，由于本次我们的游戏需要多种音效同时播放所以就选择了SoundPool类，它和Android提供常规的MediaPlayer类有哪些不同呢? </p>
<p>&nbsp; 1. SoundPool载入音乐文件使用了独立的线程，不会阻塞UI主线程的操作。但是这里Android开发网提醒大家如果音效文件过大没有载入完成，我们调用play方法时可能产生严重的后果，这里Android SDK提供了一个SoundPool.OnLoadCompleteListener类来帮助我们了解媒体文件是否载入完成，我们重载 onLoadComplete(SoundPool soundPool, int sampleId, int status) 方法即可获得。 </p>
<p>&nbsp; 2. 从上面的onLoadComplete方法可以看出该类有很多参数，比如类似id，是的SoundPool在load时可以处理多个媒体一次初始化并放入内存中，这里效率比MediaPlayer高了很多。 </p>
<p>&nbsp; 3. SoundPool类支持同时播放多个音效，这对于游戏来说是十分必要的，而MediaPlayer类是同步执行的只能一个文件一个文件的播放。 </p>
<p>&nbsp; SoundPool类使用示例代码: </p>
<p>view plaincopy to clipboardprint?<br />
SoundPool sp=new SoundPool(8, /*maxStreams*/, AudioManager.STREAM_MUSIC /*streamType*/, 100 /*srcQuality*/) ;&nbsp; <br />
SoundPool sp=new SoundPool(8, /*maxStreams*/, AudioManager.STREAM_MUSIC /*streamType*/, 100 /*srcQuality*/) ; </p>
<p>&nbsp;有关载入音效的方法，有以下几种方法 </p>
<p>view plaincopy to clipboardprint?<br />
int&nbsp; load(Context context, int resId, int priority)&nbsp; //从APK资源载入&nbsp;&nbsp; <br />
&nbsp;&nbsp; int&nbsp; load(FileDescriptor fd, long offset, long length, int priority)&nbsp; //从FileDescriptor对象载入&nbsp;&nbsp; <br />
&nbsp;&nbsp; int&nbsp; load(AssetFileDescriptor afd, int priority)&nbsp; //从Asset对象载入&nbsp;&nbsp; <br />
&nbsp;&nbsp; int&nbsp; load(String path, int priority)&nbsp; //从完整文件路径名载入&nbsp; <br />
int&nbsp; load(Context context, int resId, int priority)&nbsp; //从APK资源载入<br />
&nbsp;&nbsp; int&nbsp; load(FileDescriptor fd, long offset, long length, int priority)&nbsp; //从FileDescriptor对象载入<br />
&nbsp;&nbsp; int&nbsp; load(AssetFileDescriptor afd, int priority)&nbsp; //从Asset对象载入<br />
&nbsp;&nbsp; int&nbsp; load(String path, int priority)&nbsp; //从完整文件路径名载入 </p>
<p>我们看到了每个load的重载版本的最后一个参数为优先级，这里用于播放多个文件时，系统会优先处理不过目前Android123提示大家SDK提到了目前并没有实现，所以没有实际的效果。 </p>
<p>&nbsp;&nbsp; 对于播放，可以使用 play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)&nbsp;&nbsp; 而停止则可以使用 pause(int streamID) 方法，这里的streamID和soundID均在构造SoundPool类的第一个参数中指明了总数量，而id从0开始。</p>
<p><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034679.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339699.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:33 <a href="http://www.blogjava.net/kissyan4916/articles/339699.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十九） 分辨率大全</title><link>http://www.blogjava.net/kissyan4916/articles/339700.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:33:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339700.html</guid><description><![CDATA[<p>对于Android游戏开发我们不得不像iPhone那样思考兼容Android平板电脑，对于苹果要考虑iPad、iPhone 3GS和iPhone 4等屏幕之间的兼容性，对于几乎所有的分辨率Android123总结了大约超过20中粉笔阿女郎的大小和对应关系，对于开发Android游戏而言可以考虑到未来的3.0以及很多平板电脑的需要。 </p>
<p>&nbsp; 常规的我们可能只考虑QVGA，HVGA，WVGA，FWVGA和DVGA，但是抛去了手机不谈，可能平板使用类似 WSVGA的1024x576以及WXGA的1280x768等等。</p>
<p>QVGA = 320 * 240;<br />
WQVGA = 320 * 480;<br />
WQVGA2 = 400 * 240;<br />
WQVGA3 = 432 * 240;<br />
HVGA = 480 * 320;<br />
VGA = 640 * 480;<br />
WVGA = 800 * 480;<br />
WVGA2 = 768 * 480;<br />
FWVGA = 854 * 480;<br />
DVGA = 960 * 640;<br />
PAL = 576 * 520;<br />
NTSC = 486 * 440;<br />
SVGA = 800 * 600;<br />
WSVGA = 1024 * 576;<br />
XGA = 1024 * 768;<br />
XGAPLUS = 1152 * 864;<br />
HD720 = 1280 * 720;<br />
WXGA = 1280 * 768;<br />
WXGA2 = 1280 * 800;<br />
WXGA3 = 1280 * 854;<br />
SXGA = 1280 * 1024;<br />
WXGA4 = 1366 * 768;<br />
SXGAMINUS = 1280 * 960;<br />
SXGAPLUS = 1400 * 1050;<br />
WXGAPLUS = 1440 * 900;<br />
HD900 = 1600 * 900;<br />
WSXGA = 1600 * 1024;<br />
WSXGAPLUS = 1680 * 1050;<br />
UXGA = 1600 * 1200;<br />
HD1080 = 1920 * 1080;<br />
QWXGA = 2048 * 1152;<br />
WUXGA = 1920 * 1200;<br />
TXGA = 1920 * 1400;<br />
QXGA = 2048 * 1536;<br />
WQHD = 2560 * 1440;<br />
WQXGA = 2560 * 1600;<br />
QSXGA = 2560 * 2048;<br />
QSXGAPLUS = 2800 * 2100;<br />
WQSXGA = 3200 * 2048;<br />
QUXGA = 3200 * 2400;<br />
QFHD = 3840 * 2160;<br />
WQUXGA = 3840 * 2400;<br />
HD4K = 4096 * 2304;<br />
HXGA = 4096 * 3072;<br />
WHXGA = 5120 * 3200;<br />
HSXGA = 5120 * 4096;<br />
WHSXGA = 6400 * 4096;<br />
HUXGA = 6400 * 4800;<br />
SHV = 7680 * 4320;<br />
WHUXGA = 7680 * 4800;</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034693.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339700.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:33 <a href="http://www.blogjava.net/kissyan4916/articles/339700.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十七） 图像渐变特效</title><link>http://www.blogjava.net/kissyan4916/articles/339698.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339698.html</guid><description><![CDATA[<p>在Android游戏开发中我们不免要涉及到一些图形特效处理，今天主要看下Android平台下实现渐变效果。在 android.graphics中我们可以找到有关Gradient字样的类，比如LinearGradient 线性渐变、RadialGradient径向渐变和 角度渐变SweepGradient 三种，他们的基类为android.graphics.Shader。为了显示出效果android123使用一个简单的例子来说明。 </p>
<p>&nbsp; 一、LinearGradient线性渐变</p>
<p>&nbsp; 在android平台中提供了两种重载方式来实例化该类分别为，他们的不同之处为参数中第一种方法可以用颜色数组，和位置来实现更细腻的过渡效果，比如颜色采样int[] colors数组中存放20种颜色，则渐变将会逐一处理。而第二种方法参数仅为起初颜色color0和最终颜色color1。</p>
<p>view plaincopy to clipboardprint?<br />
LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile)&nbsp;&nbsp;&nbsp; <br />
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)&nbsp;&nbsp; <br />
LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile) <br />
LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, Shader.TileMode tile)&nbsp; </p>
<p>使用实例如下</p>
<p>view plaincopy to clipboardprint?<br />
Paint p=new Paint();&nbsp;&nbsp; <br />
&nbsp; LinearGradient lg=new LinearGradient(0,0,100,100,Color.RED,Color.BLUE,Shader.TileMode.MIRROR);&nbsp; //参数一为渐变起初点坐标x位置，参数二为y轴位置，参数三和四分辨对应渐变终点，最后参数为平铺方式，这里设置为镜像&nbsp; <br />
Paint p=new Paint();<br />
&nbsp; LinearGradient lg=new LinearGradient(0,0,100,100,Color.RED,Color.BLUE,Shader.TileMode.MIRROR);&nbsp; //参数一为渐变起初点坐标x位置，参数二为y轴位置，参数三和四分辨对应渐变终点，最后参数为平铺方式，这里设置为镜像 </p>
<p>刚才Android开发网已经讲到Gradient是基于Shader类，所以我们通过Paint的setShader方法来设置这个渐变，代码如下:</p>
<p>view plaincopy to clipboardprint?<br />
p.setShader(lg);&nbsp;&nbsp; <br />
&nbsp; canvas.drawCicle(0,0,200,p); //参数3为画圆的半径，类型为float型。&nbsp; <br />
p.setShader(lg);<br />
&nbsp; canvas.drawCicle(0,0,200,p); //参数3为画圆的半径，类型为float型。 </p>
<p>二、 RadialGradient镜像渐变 </p>
<p>&nbsp; 有了上面的基础，我们一起来了解下径向渐变。和上面参数唯一不同的是，径向渐变第三个参数是半径，其他的和线性渐变相同。</p>
<p>view plaincopy to clipboardprint?<br />
RadialGradient(float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile)&nbsp;&nbsp;&nbsp; <br />
&nbsp; RadialGradient(float x, float y, float radius, int color0, int color1, Shader.TileMode tile)&nbsp;&nbsp; <br />
RadialGradient(float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile) <br />
&nbsp; RadialGradient(float x, float y, float radius, int color0, int color1, Shader.TileMode tile)&nbsp; </p>
<p>三、 SweepGradient角度渐变 </p>
<p>&nbsp; 对于一些3D立体效果的渐变可以尝试用角度渐变来完成一个圆锥形，相对来说比上面更简单，前两个参数为中心点，然后通过载入的颜色来平均的渐变渲染。</p>
<p>view plaincopy to clipboardprint?<br />
SweepGradient(float cx, float cy, int[] colors, float[] positions)&nbsp; //对于最后一个参数SDK上的描述为May be NULL. The relative position of each corresponding color in the colors array, beginning with 0 and ending with 1.0. If the values are not monotonic, the drawing may produce unexpected results. If positions is NULL, then the colors are automatically spaced evenly.，所以Android123建议使用下面的重载方法，本方法一般为NULL即可。&nbsp;&nbsp; <br />
SweepGradient(float cx, float cy, int color0, int color1)&nbsp; </p>
<p><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034673.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339698.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:32 <a href="http://www.blogjava.net/kissyan4916/articles/339698.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十六） 异步音乐播放</title><link>http://www.blogjava.net/kissyan4916/articles/339697.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:29:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339697.html</guid><description><![CDATA[<p>在Android游戏开发中我们必须考虑背景音乐播放问题，在Android平台中提供了MediaPlayer类可以播放声音，但是游戏除了播放音乐外还需要考虑画面的流畅性，以及多种音效同时播放，所以必须用到Android多线程机制和异步音效播放。Android SDK从1.0开始就提供了AsyncPlayer类，这里我们为了根据我们自己的需要可以派生或修改出更灵活的播放类。</p>
<p>view plaincopy to clipboardprint?<br />
import android.content.Context;&nbsp;&nbsp; <br />
import android.net.Uri;&nbsp;&nbsp; <br />
import android.os.PowerManager;&nbsp;&nbsp; <br />
import android.os.SystemClock;&nbsp;&nbsp; <br />
import android.util.Log;&nbsp;&nbsp; <br />
import java.io.IOException;&nbsp;&nbsp; <br />
import java.lang.IllegalStateException;&nbsp;&nbsp; <br />
import java.util.LinkedList;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
public class AsyncPlayer {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private static final int PLAY = 1;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private static final int STOP = 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private static final boolean mDebug = false;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private static final class Command {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int code;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context context;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri uri;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean looping;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int stream;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long requestTime;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String toString() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "{ code=" + code + " looping=" + looping + " stream=" + stream&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + " uri=" + uri + " }";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private LinkedList&lt;Command&gt; mCmdQueue = new LinkedList();&nbsp; //用一个链表保存播放参数队列&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private void startSound(Command cmd) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MediaPlayer player = new MediaPlayer();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.setAudioStreamType(cmd.stream);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.setDataSource(cmd.context, cmd.uri);&nbsp; //设置媒体源，这里Android123提示大家本类的public void play (Context context, Uri uri, boolean looping, int stream) 类第二个参数Uri为媒体位置。&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.setLooping(cmd.looping);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.prepare();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.start();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mPlayer != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer.release();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer = player;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (IOException e) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.w(mTag, "error loading sound for " + cmd.uri, e);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (IllegalStateException e) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private final class Thread extends java.lang.Thread {&nbsp;&nbsp; //通过多线程方式不阻塞调用者&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super("AsyncPlayer-" + mTag);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command cmd = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {&nbsp;&nbsp; //同步方式执行&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd = mCmdQueue.removeFirst();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (cmd.code) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case PLAY:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startSound(cmd);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case STOP:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mPlayer != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer.stop();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer.release();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.w(mTag, "STOP command without a player");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mCmdQueue.size() == 0) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mThread = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; releaseWakeLock();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private String mTag;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private Thread mThread;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private MediaPlayer mPlayer;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private PowerManager.WakeLock mWakeLock;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private int mState = STOP;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public AsyncPlayer(String tag) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (tag != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mTag = tag;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mTag = "AsyncPlayer";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void play(Context context, Uri uri, boolean looping, int stream) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command cmd = new Command();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.requestTime = SystemClock.uptimeMillis(); //这里为了测试性能，传递了开始执行前的系统tickcount计时器值&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.code = PLAY;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.context = context;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.uri = uri;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.looping = looping;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.stream = stream;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enqueueLocked(cmd);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mState = PLAY;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void stop() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mState != STOP) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command cmd = new Command();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.requestTime = SystemClock.uptimeMillis();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.code = STOP;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enqueueLocked(cmd);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mState = STOP;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private void enqueueLocked(Command cmd) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mCmdQueue.add(cmd);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mThread == null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acquireWakeLock();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mThread = new Thread();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mThread.start();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp; <br />
import android.content.Context;<br />
import android.net.Uri;<br />
import android.os.PowerManager;<br />
import android.os.SystemClock;<br />
import android.util.Log;<br />
import java.io.IOException;<br />
import java.lang.IllegalStateException;<br />
import java.util.LinkedList;<br />
&nbsp;<br />
public class AsyncPlayer {<br />
&nbsp;&nbsp;&nbsp; private static final int PLAY = 1;<br />
&nbsp;&nbsp;&nbsp; private static final int STOP = 2;<br />
&nbsp;&nbsp;&nbsp; private static final boolean mDebug = false;<br />
&nbsp;&nbsp;&nbsp; private static final class Command {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int code;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Context context;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri uri;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean looping;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int stream;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long requestTime;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String toString() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "{ code=" + code + " looping=" + looping + " stream=" + stream<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + " uri=" + uri + " }";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private LinkedList&lt;Command&gt; mCmdQueue = new LinkedList();&nbsp; //用一个链表保存播放参数队列<br />
&nbsp;&nbsp;&nbsp; private void startSound(Command cmd) {<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MediaPlayer player = new MediaPlayer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.setAudioStreamType(cmd.stream);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.setDataSource(cmd.context, cmd.uri);&nbsp; //设置媒体源，这里Android123提示大家本类的public void play (Context context, Uri uri, boolean looping, int stream) 类第二个参数Uri为媒体位置。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.setLooping(cmd.looping);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.prepare();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; player.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mPlayer != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer.release();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer = player;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (IOException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.w(mTag, "error loading sound for " + cmd.uri, e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (IllegalStateException e) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.w(mTag, "IllegalStateException (content provider died?) " + cmd.uri, e);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private final class Thread extends java.lang.Thread {&nbsp;&nbsp; //通过多线程方式不阻塞调用者<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super("AsyncPlayer-" + mTag);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command cmd = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {&nbsp;&nbsp; //同步方式执行<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd = mCmdQueue.removeFirst();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (cmd.code) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case PLAY:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startSound(cmd);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case STOP:<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mPlayer != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer.stop();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer.release();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mPlayer = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.w(mTag, "STOP command without a player");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mCmdQueue.size() == 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mThread = null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; releaseWakeLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private String mTag;<br />
&nbsp;&nbsp;&nbsp; private Thread mThread;<br />
&nbsp;&nbsp;&nbsp; private MediaPlayer mPlayer;<br />
&nbsp;&nbsp;&nbsp; private PowerManager.WakeLock mWakeLock;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; private int mState = STOP;<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; public AsyncPlayer(String tag) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (tag != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mTag = tag;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mTag = "AsyncPlayer";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; public void play(Context context, Uri uri, boolean looping, int stream) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command cmd = new Command();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.requestTime = SystemClock.uptimeMillis(); //这里为了测试性能，传递了开始执行前的系统tickcount计时器值<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.code = PLAY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.context = context;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.uri = uri;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.looping = looping;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.stream = stream;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enqueueLocked(cmd);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mState = PLAY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; <br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp; public void stop() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mCmdQueue) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mState != STOP) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Command cmd = new Command();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.requestTime = SystemClock.uptimeMillis();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cmd.code = STOP;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enqueueLocked(cmd);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mState = STOP;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; private void enqueueLocked(Command cmd) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mCmdQueue.add(cmd);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mThread == null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; acquireWakeLock();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mThread = new Thread();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mThread.start();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; } </p>
<p>一般对于Android游戏而言下面的代码不用考虑，一般用户都在交互操作，不会出现屏幕锁问题</p>
<p>view plaincopy to clipboardprint?<br />
public void setUsesWakeLock(Context context) {&nbsp; //电源管理wakelock处理&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mWakeLock != null || mThread != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + " mThread=" + mThread);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private void acquireWakeLock() {&nbsp;&nbsp; //加锁&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mWakeLock != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mWakeLock.acquire();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private void releaseWakeLock() { //解锁&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mWakeLock != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mWakeLock.release();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
}&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034662.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:29 <a href="http://www.blogjava.net/kissyan4916/articles/339697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Android游戏开发之旅（十四） 游戏开发实战一</title><link>http://www.blogjava.net/kissyan4916/articles/339695.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:28:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339695.html</guid><description><![CDATA[<p>从今天开始Android123将开始带领大家进入Android游戏开发实战篇，本次我们首个游戏为2D的基于SurfaceView的类似横版卷轴游戏。第一天我们说下需要做哪些准备: </p>
<p>&nbsp; 一、游戏地图编辑器，在J2ME时代我们可能都是用GIF分割多帧或BMP上放置多个图片通过减少文件头来压缩体积，但是在Android平台上开发游戏我们不需要那么节省，不过资源的释放仍然很重要，否则会出现OutOfMemoryError这样的悲剧发生。一般简单的2D平面游戏地图都是使用二维数组来标记的。我们可以想象矩阵中的每个元素对应每个图片资源。详细的存储方法我们将在下次具体讲到。</p>
<p>&nbsp; 二、控制方式，由于横版过关类游戏不适合重力感应操作，我们这里选择屏幕下方加设一个区域，放置上、下、左、右按键，同时右侧给出常用的攻击、跳跃按钮，而游戏的暂停可以通过触控实现继续或暂停。</p>
<p>&nbsp; 三、音效处理，常规的一般在攻击比如出拳、发射子弹的过程中有音效，或对手自己中弹（当然对于Android图形开发来说就是碰撞检测）时发出音效，跳跃、过关均会需要一些声音素材文件，一般的游戏还需要背景音乐配合烘托游戏气氛。</p>
<p>&nbsp; 四、游戏逻辑，这是主要的地方，我们将通过实例代码让大家了解游戏开发中是如何的卷轴、人物的跳跃、攻击有效判断即碰撞检测，电脑智能等算法问题。</p>
<p>&nbsp; 五、细节处理，比如计分，等级，游戏计时，关卡档案的存档，读取以及开场设计，关卡过渡的过场动画处理。</p>
<p>&nbsp; 这里Android开发网提示大家，目前很多J2ME的游戏可以轻松的移植到Android平台，主要的细节只要了解Google Android平台的图形相关问题即可，主要是Bitmap、Drawable和View线程处理问题。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034645.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339695.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:28 <a href="http://www.blogjava.net/kissyan4916/articles/339695.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十五） 按键中断处理</title><link>http://www.blogjava.net/kissyan4916/articles/339696.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:28:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339696.html</guid><description><![CDATA[<p>有关Android平台上游戏开发中我们需要处理一些特别的按键事件，对于突发的事情我们需要特别的考虑，比如突然来电话了和游戏中按下一些特殊的键，比如拍照键</p>
<p>view plaincopy to clipboardprint?<br />
@Override&nbsp; <br />
&nbsp;&nbsp;&nbsp; public boolean dispatchKeyEvent(KeyEvent event)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (event.getKeyCode())&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_VOLUME_UP:&nbsp;&nbsp; //音量键+&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_VOLUME_DOWN:&nbsp;&nbsp; //音量键-&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_CAMERA:&nbsp; //拍照键&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_FOCUS:&nbsp;&nbsp; //拍照键半按的对焦状态&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; event.getAction() == KeyEvent.ACTION_UP&nbsp;&nbsp; //Android123提示如果按键按下后弹起时触发&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true; //这些标记为处理过，则不在往内部传递&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.dispatchKeyEvent(event);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp; <br />
@Override<br />
&nbsp;&nbsp;&nbsp; public boolean dispatchKeyEvent(KeyEvent event)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (event.getKeyCode())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_VOLUME_UP:&nbsp;&nbsp; //音量键+<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_VOLUME_DOWN:&nbsp;&nbsp; //音量键-<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_CAMERA:&nbsp; //拍照键<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_FOCUS:&nbsp;&nbsp; //拍照键半按的对焦状态<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; event.getAction() == KeyEvent.ACTION_UP&nbsp;&nbsp; //Android123提示如果按键按下后弹起时触发<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true; //这些标记为处理过，则不在往内部传递<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.dispatchKeyEvent(event);<br />
&nbsp;&nbsp;&nbsp; } </p>
<p>对于游戏突然来电话我们一般采取通过PhoneStateListener类提供的public void onCallStateChanged (int state, String incomingNumber) 回调方法可以获取电话的状态，比如常规空闲时CALL_STATE_IDLE、来电时<br />
CALL_STATE_RINGING和 CALL_STATE_OFFHOOK 摘机通话中，有关处理的细节网友可以查看Android Git项目中的Music，在Android开源项目中系统自带的音乐播放器可以很好的处理，比如在通话结束后恢复音乐播放，而我们游戏需要做的就是记住当前的游戏状态尽量数据持久化处理，不能因为长时间的通话，游戏的Activity被清理了，这里我们一般通过onSaveInstanceState来保存当前窗口的一些记录，通过Intent标记来让系统管理好我们游戏的生命周期。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034653.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339696.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:28 <a href="http://www.blogjava.net/kissyan4916/articles/339696.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十二）Sensor重力感应（2）</title><link>http://www.blogjava.net/kissyan4916/articles/339694.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339694.html</guid><description><![CDATA[<p>有关Android游戏开发中的Sensor感应示例今天我们将一起来讨论，对于目前最新的Android 2.2平台 而言仍然没有具体的感应判断逻辑，下面我们一起定义 下常用的感应动作事件。首先Android123提醒大家由于是三轴的立体空间感应所以相对于轨迹球、导航键的上下左右外，还提供了前后的感应，所以我们定义最基本的六种空间方向。 </p>
<p>view plaincopy to clipboardprint?<br />
public static final int CWJ_UP = 0;&nbsp;&nbsp; <br />
public static final int CWJ_DOWN = 1;&nbsp;&nbsp; <br />
public static final int CWJ_LEFT = 2;&nbsp;&nbsp; <br />
public static final int CWJ_RIGHT = 4;&nbsp;&nbsp; <br />
public static final int CWJ_FORWARD = 8; //向前&nbsp;&nbsp; <br />
public static final int CWJ_BACKWARD = 16; //向后&nbsp; <br />
public static final int CWJ_UP = 0;<br />
public static final int CWJ_DOWN = 1;<br />
public static final int CWJ_LEFT = 2;<br />
public static final int CWJ_RIGHT = 4;<br />
public static final int CWJ_FORWARD = 8; //向前<br />
public static final int CWJ_BACKWARD = 16; //向后 </p>
<p>下面我们做精确的角度旋转修正值定义，我们用到yaw、pitch和roll，相信学过3D开发的网友不会对这些陌生的，我们就把他们对应为绕y、x、z 轴的角度好了，如果你们没有学过3D相关的知识这里Android开发网推荐大家可以通过Cube例子 自定义Render来观察这三个值对应立方体的旋转角度。<br />
Yaw在(0,0,0)中， 以xOz的坐标平面中围绕y轴旋转，如果是负角则我们定义为CWJ_YAW_LEFT 即往左边倾斜，同理我们定义如下: </p>
<p>view plaincopy to clipboardprint?<br />
public static final int CWJ_YAW_LEFT = 0;&nbsp;&nbsp; <br />
public static final int CWJ_YAW_RIGHT = 1;&nbsp;&nbsp; <br />
public static final int CWJ_PITCH_UP = 2;&nbsp;&nbsp; <br />
public static final int CWJ_PITCH_DOWN = 4;&nbsp;&nbsp; <br />
public static final int CWJ_ROLL_LEFT = 8;&nbsp;&nbsp; <br />
public static final int CWJ_ROLL_RIGHT = 16;&nbsp; <br />
public static final int CWJ_YAW_LEFT = 0;<br />
public static final int CWJ_YAW_RIGHT = 1;<br />
public static final int CWJ_PITCH_UP = 2;<br />
public static final int CWJ_PITCH_DOWN = 4;<br />
public static final int CWJ_ROLL_LEFT = 8;<br />
public static final int CWJ_ROLL_RIGHT = 16; </p>
<p>我们通过加速感应器可以获得SensorEvent的四个值，今天Android123给大家一个简单示例，不考虑其他因素，在public int accuracy 、public Sensor sensor 、public long timestamp&nbsp; 和&nbsp; public final float[] values 中，我们获取values的浮点数组来判断方向。</p>
<p>view plaincopy to clipboardprint?<br />
int nAndroid123=CWJ_UP //向上&nbsp;&nbsp; <br />
float ax = values[0];&nbsp;&nbsp; <br />
float ay = values[1];&nbsp;&nbsp; <br />
float az = values[2];&nbsp;&nbsp; <br />
&nbsp; <br />
float absx = Math.abs(ax);&nbsp;&nbsp; <br />
float absy = Math.abs(ay);&nbsp;&nbsp; <br />
float absz = Math.abs(az);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
if (absx &gt; absy &amp;&amp; absx &gt; absz) {&nbsp;&nbsp; <br />
if (ax &gt; 0) {&nbsp;&nbsp; <br />
&nbsp; nAndroid123 = CWJ_RIGHT;&nbsp;&nbsp; <br />
} else {&nbsp;&nbsp; <br />
&nbsp; nAndroid123 = CWJ_LEFT;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
} else if (absy &gt; absx &amp;&amp; absy &gt; absz) {&nbsp;&nbsp; <br />
&nbsp; <br />
if (ay &gt; 0) {&nbsp;&nbsp; <br />
nAndroid123= CWJ_FORWARD;&nbsp;&nbsp; <br />
} else {&nbsp;&nbsp; <br />
nAndroid123= CWJ_BACKWARD;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
} else if (absz &gt; absx &amp;&amp; absz &gt; absy) {&nbsp;&nbsp; <br />
if (az &gt; 0) {&nbsp;&nbsp; <br />
&nbsp; nAndroid123 = CWJ_UP;&nbsp;&nbsp; <br />
} else {&nbsp;&nbsp; <br />
&nbsp; nAndroid123 = CWJ_DOWN;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
} else {&nbsp;&nbsp; <br />
nAndroid123 = CWJ_UNKNOWN;&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nAndroid123=CWJ_UP //向上<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float ax = values[0];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float ay = values[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float az = values[2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float absx = Math.abs(ax);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float absy = Math.abs(ay);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float absz = Math.abs(az);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (absx &gt; absy &amp;&amp; absx &gt; absz) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ax &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nAndroid123 = CWJ_RIGHT;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nAndroid123 = CWJ_LEFT;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (absy &gt; absx &amp;&amp; absy &gt; absz) {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ay &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nAndroid123= CWJ_FORWARD;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nAndroid123= CWJ_BACKWARD;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (absz &gt; absx &amp;&amp; absz &gt; absy) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (az &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nAndroid123 = CWJ_UP;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nAndroid123 = CWJ_DOWN;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nAndroid123 = CWJ_UNKNOWN;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p>有关偏向角度问题，我们将在下一次详细讲述，对于一般的2D游戏，我们可以参考本文来实现重力控制，所以总体来说Android游戏开发比较简单易懂，Android平台使用的Java 语言还是很适合做游戏的。在逻辑表达上更清晰。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034640.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339694.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:27 <a href="http://www.blogjava.net/kissyan4916/articles/339694.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十二）Sensor重力感应（1） </title><link>http://www.blogjava.net/kissyan4916/articles/339693.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:26:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339693.html</guid><description><![CDATA[<p>从Android手机 开始，主流的智能机纷纷加入了感应器Sensor硬件，常见的有光线感应器、重力感应器、加速感应器，而更高级的有磁极方向、陀螺仪、距离感应器、温度感应器等等。对于Android游戏 开发 ，我们主要用到重力、加速、磁力和陀螺仪四种，当然部分游戏可能需要GPS 或Cellid定位来修正一些位移信息。从系统 中提高的感应器主要在android .hardware中，我们可以看到系统提供了 android.hardware.SensorEventListener、Sensor和SensorManager这三个类，我们会发现除了可以获取 感应器的信息，和感应器的原始数据 外，并没有提供相关的逻辑处理。Android123将会分3篇来详细的介绍不同感应器的作用和逻辑处理，比如自由落体，晃动，磁极，当前的旋转速度。</p>
<p>未来Android123将完成主要是一个基于OpenGL 3D的雷电游戏，最终加入联网对战效果 可以团队打怪实现手机3D网游充分发挥Android手机的娱乐能力。对于大多数新款Android手机可能没有配备轨迹球或导航键的方向控制，所以重力感应器是这类实时性较强游戏的首选控制方式。主要有以下几点问题对于Sensor</p>
<p>1. 降噪处理，如果做过LBS软件 的大家可能明白偏移修正，在GPS无法正常获取数据较间断时地图不能乱飘，这里Sensor也不例外，除了使用采样数据平均值获取外，可以间隔采样的方法来处理。细节的算法我们将在下节给出示例代码 。</p>
<p>2. 感应器的敏感度，在Android中提供了四种延迟级别分别为</p>
<p>SENSOR_DELAY_FASTEST 最低延迟，一般不是特别敏感的处理不推荐 使用，该种模式可能造成手机电力大量消耗，由于传递的为原始数据，算法不处理好将会影响游戏逻辑和UI的性能，所以Android开发网不推荐大家使用。</p>
<p>SENSOR_DELAY_GAME 游戏延迟，一般绝大多数的实时性较高的游戏都使用该级别。<br />
int SENSOR_DELAY_NORMAL 标准延迟，对于一般的益智类或EASY级别的游戏可以使用，但过低的采样率可能对一些赛车类游戏有跳帧现象。<br />
int SENSOR_DELAY_UI 用户界面 延迟，一般对于屏幕 方向自动 旋转使用，相对节省电能和逻辑处理，一般游戏开发中我们不使用。</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034586.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339693.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:26 <a href="http://www.blogjava.net/kissyan4916/articles/339693.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十一）View中手势识别</title><link>http://www.blogjava.net/kissyan4916/articles/339692.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:25:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339692.html</guid><description><![CDATA[<p>有关Android平台 的游戏 开发 中我们需要涉及到控制，在开始的Android游戏开发之旅 中我们提到了按键和轨迹球的控制方式，从今天开始 Android123开始给出大家游戏中其他的一些控制方式，比如今天的手势操作和未来重力感应。</p>
<p>很多网友发现Android中手势识别提供了两个类，由于Android 1.6以下的版本比如cupcake中无法使用android .view.GestureDetector，而 android.gesture.Gesture是Android 1.6才开始支持的，我们考虑到仍然有很多Android 1.5固件的网友，就来看下兼容性更强的android.view.GestureDetector。在 android.view.GestureDetector类中有很多种重载版本，下面我们仅提到能够自定义 在View 中的两种方法，分别为 GestureDetector(Context context, GestureDetector.OnGestureListener listener) 和 GestureDetector(Context context, GestureDetector.OnGestureListener listener, Handler handler) 和。我们可以看到第一个参数为Context，所以我们想附着到某View时，最简单的方法就是直接从超类派生传递Context，实现 GestureDetector里中提供一些接口。</p>
<p>下面我们就以实现手势识别的onFling动作，在CwjView中我们从View类继承，当然大家可以从TextView 等更高层的界面 中实现触控。</p>
<p>view plaincopy to clipboardprint?<br />
class CwjView extends View {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; private GestureDetector mGD;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public CwjView(Context context, AttributeSet attrs) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGD = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int dx = (int) (e2.getX() - e1.getX()); //计算滑动的距离&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Math.abs(dx) &gt; MAJOR_MOVE &amp;&amp; Math.abs(velocityX) &gt; Math.abs(velocityY)) { //降噪处理，必须有较大的动作才识别&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (velocityX &gt; 0) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //向右边&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //向左边&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp; //当然可以处理velocityY处理向上和向下的动作&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp; <br />
class CwjView extends View {<br />
&nbsp;&nbsp;&nbsp; private GestureDetector mGD;<br />
&nbsp;&nbsp;&nbsp; public CwjView(Context context, AttributeSet attrs) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs);<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGD = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int dx = (int) (e2.getX() - e1.getX()); //计算滑动的距离<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Math.abs(dx) &gt; MAJOR_MOVE &amp;&amp; Math.abs(velocityX) &gt; Math.abs(velocityY)) { //降噪处理，必须有较大的动作才识别<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (velocityX &gt; 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //向右边<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //向左边<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp; //当然可以处理velocityY处理向上和向下的动作<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />
&nbsp;&nbsp;&nbsp; } </p>
<p>在上面Android123提示大家仅仅探测了Fling动作仅仅实现了onFling方法，这里相关的还有以下几种方法来实现具体的可以参考我们以前的文章有详细的解释: </p>
<p>view plaincopy to clipboardprint?<br />
&nbsp;&nbsp;&nbsp; <br />
boolean&nbsp; onDoubleTap(MotionEvent e)&nbsp;&nbsp; <br />
boolean&nbsp; onDoubleTapEvent(MotionEvent e)&nbsp;&nbsp;&nbsp; <br />
boolean&nbsp; onDown(MotionEvent e)&nbsp;&nbsp;&nbsp; <br />
void&nbsp; onLongPress(MotionEvent e)&nbsp;&nbsp;&nbsp; <br />
boolean&nbsp; onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)&nbsp;&nbsp;&nbsp; <br />
void&nbsp; onShowPress(MotionEvent e)&nbsp;&nbsp;&nbsp; <br />
boolean&nbsp; onSingleTapConfirmed(MotionEvent e)&nbsp;&nbsp;&nbsp; <br />
boolean&nbsp; onSingleTapUp(MotionEvent e)&nbsp;&nbsp; <br />
&nbsp;<br />
boolean&nbsp; onDoubleTap(MotionEvent e)<br />
boolean&nbsp; onDoubleTapEvent(MotionEvent e) <br />
boolean&nbsp; onDown(MotionEvent e) <br />
void&nbsp; onLongPress(MotionEvent e) <br />
boolean&nbsp; onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) <br />
void&nbsp; onShowPress(MotionEvent e) <br />
boolean&nbsp; onSingleTapConfirmed(MotionEvent e) <br />
boolean&nbsp; onSingleTapUp(MotionEvent e)&nbsp; </p>
<p>接下来是重点，让我们的View接受触控，需要使用下面两个方法让GestureDetector类去处理onTouchEvent和 onInterceptTouchEvent方法。</p>
<p>view plaincopy to clipboardprint?<br />
@Override&nbsp; <br />
public boolean onTouchEvent(MotionEvent event) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; mGD.onTouchEvent(event);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
@Override&nbsp; <br />
public boolean onInterceptTouchEvent(MotionEvent event) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; return mGD.onTouchEvent(event);&nbsp;&nbsp; <br />
}&nbsp;&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034582.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:25 <a href="http://www.blogjava.net/kissyan4916/articles/339692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（九）VideoView类剖析</title><link>http://www.blogjava.net/kissyan4916/articles/339690.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:24:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339690.html</guid><description><![CDATA[<p>有关SurfaceView 相关的内容今天Android123继续延用系统 的示例类VideoView来让大家深入了解Android平台 的图形绘制基础类的实现原理。大家可能会发现VideoView类的控制方面无法改变，我们可以通过重构VideoView类来实现更个性化的播放 器</p>
<p>view plaincopy to clipboardprint?<br />
public class VideoView extends SurfaceView implements MediaPlayerControl {&nbsp;&nbsp; <br />
&nbsp; private String TAG = "VideoView";&nbsp;&nbsp; <br />
&nbsp; // settable by the client&nbsp;&nbsp; <br />
&nbsp; private Uri&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mUri;&nbsp;&nbsp; <br />
&nbsp; private int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDuration;&nbsp;&nbsp; <br />
&nbsp; // all possible internal states&nbsp;&nbsp; <br />
&nbsp; private static final int STATE_ERROR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = -1;&nbsp;&nbsp; <br />
&nbsp; private static final int STATE_IDLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0;&nbsp;&nbsp; <br />
&nbsp; private static final int STATE_PREPARING&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 1;&nbsp;&nbsp; <br />
&nbsp; private static final int STATE_PREPARED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 2;&nbsp;&nbsp; <br />
&nbsp; private static final int STATE_PLAYING&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 3;&nbsp;&nbsp; <br />
&nbsp; private static final int STATE_PAUSED&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 4;&nbsp;&nbsp; <br />
&nbsp; private static final int STATE_PLAYBACK_COMPLETED = 5;&nbsp;&nbsp; <br />
&nbsp; // mCurrentState is a VideoView object's current state.&nbsp;&nbsp; <br />
&nbsp; // mTargetState is the state that a method caller intends to reach.&nbsp;&nbsp; <br />
&nbsp; // For instance, regardless the VideoView object's current state,&nbsp;&nbsp; <br />
&nbsp; // calling pause() intends to bring the object to a target state&nbsp;&nbsp; <br />
&nbsp; // of STATE_PAUSED.&nbsp;&nbsp; <br />
&nbsp; private int mCurrentState = STATE_IDLE;&nbsp;&nbsp; <br />
&nbsp; private int mTargetState&nbsp; = STATE_IDLE;&nbsp;&nbsp; <br />
&nbsp; // All the stuff we need for playing and showing a video&nbsp;&nbsp; <br />
&nbsp; private SurfaceHolder mSurfaceHolder = null;&nbsp;&nbsp; <br />
&nbsp; private MediaPlayer mMediaPlayer = null;&nbsp;&nbsp; <br />
&nbsp; private int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mVideoWidth;&nbsp;&nbsp; <br />
&nbsp; private int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mVideoHeight;&nbsp;&nbsp; <br />
&nbsp; private int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mSurfaceWidth;&nbsp;&nbsp; <br />
&nbsp; private int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mSurfaceHeight;&nbsp;&nbsp; <br />
&nbsp; private MediaController mMediaController;&nbsp;&nbsp; <br />
&nbsp; private OnCompletionListener mOnCompletionListener;&nbsp;&nbsp; <br />
&nbsp; private MediaPlayer.OnPreparedListener mOnPreparedListener;&nbsp;&nbsp; <br />
&nbsp; private int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mCurrentBufferPercentage;&nbsp;&nbsp; <br />
&nbsp; private OnErrorListener mOnErrorListener;&nbsp;&nbsp; <br />
&nbsp; private int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mSeekWhenPrepared;&nbsp; // recording the seek position while preparing&nbsp;&nbsp; <br />
&nbsp; private boolean&nbsp;&nbsp;&nbsp; mCanPause;&nbsp;&nbsp; <br />
&nbsp; private boolean&nbsp;&nbsp;&nbsp; mCanSeekBack;&nbsp;&nbsp; <br />
&nbsp; private boolean&nbsp;&nbsp;&nbsp; mCanSeekForward;&nbsp;&nbsp; <br />
&nbsp; public VideoView(Context context) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initVideoView();&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp; public VideoView(Context context, AttributeSet attrs) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this(context, attrs, 0);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initVideoView();&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp; public VideoView(Context context, AttributeSet attrs, int defStyle) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs, defStyle);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initVideoView();&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Log.i("@@@@", "onMeasure");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int width = getDefaultSize(mVideoWidth, widthMeasureSpec);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int height = getDefaultSize(mVideoHeight, heightMeasureSpec);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mVideoWidth &gt; 0 &amp;&amp; mVideoHeight &gt; 0) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if ( mVideoWidth * height&nbsp; &gt; width * mVideoHeight ) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Log.i("@@@", "image too tall, correcting");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height = width * mVideoHeight / mVideoWidth;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if ( mVideoWidth * height&nbsp; &lt; width * mVideoHeight ) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Log.i("@@@", "image too wide, correcting");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width = height * mVideoWidth / mVideoHeight;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Log.i("@@@", "aspect ratio is correct: " +&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //width+"/"+height+"="+&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //mVideoWidth+"/"+mVideoHeight);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Log.i("@@@@@@@@@@", "setting size: " + width + 'x' + height);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setMeasuredDimension(width, height);&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp; public int resolveAdjustedSize(int desiredSize, int measureSpec) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int result = desiredSize;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int specMode = MeasureSpec.getMode(measureSpec);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int specSize =&nbsp; MeasureSpec.getSize(measureSpec);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (specMode) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case MeasureSpec.UNSPECIFIED:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Parent says we can be as big as we want. Just don't be larger&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * than max size imposed on ourselves.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = desiredSize;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case MeasureSpec.AT_MOST:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Parent says we can be as big as we want, up to specSize.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Don't be larger than specSize, and don't be larger than&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * the max size imposed on ourselves.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = Math.min(desiredSize, specSize);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case MeasureSpec.EXACTLY:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // No choice. Do what we are told.&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = specSize;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;&nbsp;&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034570.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:24 <a href="http://www.blogjava.net/kissyan4916/articles/339690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（十）位图旋转</title><link>http://www.blogjava.net/kissyan4916/articles/339691.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:24:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339691.html</guid><description><![CDATA[<p>在Android中图形的旋转和变化提供了方便的矩阵Maxtrix类，Maxtrix类的setRotate方法接受图形的变换角度和缩放，最终Bitmap类的createBitmap方法中其中的重载函数，可以接受Maxtrix对象，方法原型如下</p>
<p>view plaincopy to clipboardprint?<br />
public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)&nbsp; <br />
public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter) </p>
<p>参数的具体意思<br />
source 源 bitmap对象<br />
x&nbsp; 源坐标x位置<br />
y 源坐标y位置<br />
width&nbsp; 宽度<br />
height&nbsp; 高度<br />
m&nbsp; 接受的maxtrix对象，如果没有可以设置 为null<br />
filter 该参数仅对maxtrix包含了超过一个翻转才有效。</p>
<p>下面Android123给大家一个比较经典的例子 ，rotate方法是静态方法可以直接调用，参数为源Bitmap对象，参数二为旋转的角度，从 0~360，返回值为新的Bitmap对象。其中具体的宽高可以调整。</p>
<p>view plaincopy to clipboardprint?<br />
public static Bitmap rotate(Bitmap b, int degrees) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (degrees != 0 &amp;&amp; b != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matrix m = new Matrix();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m.setRotate(degrees,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (float) b.getWidth() / 2, (float) b.getHeight() / 2);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bitmap b2 = Bitmap.createBitmap(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b, 0, 0, b.getWidth(), b.getHeight(), m, true);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (b != b2) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.recycle();&nbsp; //Android开发网再次提示Bitmap操作完应该显示的释放&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b = b2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (OutOfMemoryError ex) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Android123建议大家如何出现了内存不足异常，最好return 原始的bitmap对象。.&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return b;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp; <br />
public static Bitmap rotate(Bitmap b, int degrees) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (degrees != 0 &amp;&amp; b != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matrix m = new Matrix();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m.setRotate(degrees,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (float) b.getWidth() / 2, (float) b.getHeight() / 2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bitmap b2 = Bitmap.createBitmap(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b, 0, 0, b.getWidth(), b.getHeight(), m, true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (b != b2) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.recycle();&nbsp; //Android开发网再次提示Bitmap操作完应该显示的释放<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b = b2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (OutOfMemoryError ex) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Android123建议大家如何出现了内存不足异常，最好return 原始的bitmap对象。.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return b;<br />
&nbsp;&nbsp;&nbsp; } </p>
<p>补充一点吧：水平翻转<br />
view plaincopy to clipboardprint?<br />
public static Bitmap rotate(Bitmap b, int degrees) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (degrees != 0 &amp;&amp; b != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Matrix m = new Matrix();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m.postScale(1, -1);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m.setRotate(degrees,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (float) b.getWidth() / 2, (float) b.getHeight() / 2);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bitmap b2 = Bitmap.createBitmap(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b, 0, 0, b.getWidth(), b.getHeight(), m, true);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (b != b2) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.recycle();&nbsp; //Android开发网再次提示Bitmap操作完应该显示的释放&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b = b2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (OutOfMemoryError ex) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Android123建议大家如何出现了内存不足异常，最好return 原始的bitmap对象。.&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return b;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }&nbsp; </p>
<p><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034572.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339691.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:24 <a href="http://www.blogjava.net/kissyan4916/articles/339691.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（八）SurfaceView类实例</title><link>http://www.blogjava.net/kissyan4916/articles/339688.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:21:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339688.html</guid><description><![CDATA[<p>有关SurfaceView 我们将通过三个系统 自带的例子 来深入掌握Android绘图必会的SurfaceView，今天我们以SDK中的Sample 游戏 lunarlander中的LunarView具体实现，Android123建议大家导入该游戏工程到你的Eclipse 然后自己编译 先玩一下这个游戏，然后再看代码 比较好理解。</p>
<p>view plaincopy to clipboardprint?<br />
class LunarView extends SurfaceView implements SurfaceHolder.Callback {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; class LunarThread extends Thread {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Difficulty setting constants&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int DIFFICULTY_EASY = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int DIFFICULTY_HARD = 1;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int DIFFICULTY_MEDIUM = 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Physics constants&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_DOWN_ACCEL_SEC = 35;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_FIRE_ACCEL_SEC = 80;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_FUEL_INIT = 60;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_FUEL_MAX = 100;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_FUEL_SEC = 10;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_SLEW_SEC = 120; // degrees/second rotate&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_SPEED_HYPERSPACE = 180;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_SPEED_INIT = 30;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int PHYS_SPEED_MAX = 120;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * State-tracking constants&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int STATE_LOSE = 1;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int STATE_PAUSE = 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int STATE_READY = 3;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int STATE_RUNNING = 4;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int STATE_WIN = 5;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Goal condition constants&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int TARGET_ANGLE = 18; // &gt; this angle means crash&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int TARGET_BOTTOM_PADDING = 17; // px below gear&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int TARGET_PAD_HEIGHT = 8; // how high above ground&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int TARGET_SPEED = 28; // &gt; this speed means crash&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final double TARGET_WIDTH = 1.6; // width of target&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * UI constants (i.e. the speed &amp; fuel bars)&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int UI_BAR = 100; // width of the bar(s)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static final int UI_BAR_HEIGHT = 10; // height of the bar(s)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_DIFFICULTY = "mDifficulty";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_DX = "mDX";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_DY = "mDY";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_FUEL = "mFuel";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_GOAL_ANGLE = "mGoalAngle";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_GOAL_SPEED = "mGoalSpeed";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_GOAL_WIDTH = "mGoalWidth";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_GOAL_X = "mGoalX";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_HEADING = "mHeading";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_LANDER_HEIGHT = "mLanderHeight";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_LANDER_WIDTH = "mLanderWidth";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_WINS = "mWinsInARow";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_X = "mX";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private static final String KEY_Y = "mY";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Member (state) fields&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** The drawable to use as the background of the animation canvas */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Bitmap mBackgroundImage;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Current height of the surface/canvas.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @see #setSurfaceSize&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mCanvasHeight = 1;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Current width of the surface/canvas.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @see #setSurfaceSize&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mCanvasWidth = 1;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** What to draw for the Lander when it has crashed */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Drawable mCrashedImage;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Current difficulty -- amount of fuel, allowed angle, etc. Default is&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * MEDIUM.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mDifficulty;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Velocity dx. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private double mDX;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Velocity dy. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private double mDY;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Is the engine burning? */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private boolean mEngineFiring;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** What to draw for the Lander when the engine is firing */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Drawable mFiringImage;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Fuel remaining */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private double mFuel;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Allowed angle. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mGoalAngle;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Allowed speed. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mGoalSpeed;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Width of the landing pad. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mGoalWidth;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** X of the landing pad. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mGoalX;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Message handler used by thread to interact with TextView */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Handler mHandler;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Lander heading in degrees, with 0 up, 90 right. Kept in the range&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 0..360.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private double mHeading;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Pixel height of lander image. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mLanderHeight;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** What to draw for the Lander in its normal state */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Drawable mLanderImage;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Pixel width of lander image. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mLanderWidth;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Used to figure out elapsed time between frames */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private long mLastTime;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Paint to draw the lines on screen. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Paint mLinePaint;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** "Bad" speed-too-high variant of the line color. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private Paint mLinePaintBad;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** The state of the game. One of READY, RUNNING, PAUSE, LOSE, or WIN */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mMode;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Currently rotating, -1 left, 0 none, 1 right. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mRotating;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Indicate whether the surface has been created &amp; is ready to draw */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private boolean mRun = false;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Scratch rect object. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private RectF mScratchRect;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Handle to the surface manager object we interact with */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private SurfaceHolder mSurfaceHolder;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Number of wins in a row. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private int mWinsInARow;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** X of lander center. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private double mX;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** Y of lander center. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private double mY;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public LunarThread(SurfaceHolder surfaceHolder, Context context,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Handler handler) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // get handles to some important objects&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mSurfaceHolder = surfaceHolder;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mHandler = handler;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mContext = context;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Resources res = context.getResources();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // cache handles to our key sprites &amp; other drawables&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLanderImage = context.getResources().getDrawable(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R.drawable.lander_plain);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mFiringImage = context.getResources().getDrawable(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R.drawable.lander_firing);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mCrashedImage = context.getResources().getDrawable(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R.drawable.lander_crashed);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // load background image as a Bitmap instead of a Drawable b/c&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // we don't need to transform it and it's faster to draw this way&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mBackgroundImage = BitmapFactory.decodeResource(res,&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R.drawable.earthrise);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Use the regular lander image as the model size for all sprites&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLanderWidth = mLanderImage.getIntrinsicWidth();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLanderHeight = mLanderImage.getIntrinsicHeight();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Initialize paints for speedometer&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLinePaint = new Paint();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLinePaint.setAntiAlias(true);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLinePaint.setARGB(255, 0, 255, 0);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLinePaintBad = new Paint();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLinePaintBad.setAntiAlias(true);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLinePaintBad.setARGB(255, 120, 180, 0);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mScratchRect = new RectF(0, 0, 0, 0);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mWinsInARow = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDifficulty = DIFFICULTY_MEDIUM;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // initial show-up of lander (not yet playing)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mX = mLanderWidth;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mY = mLanderHeight * 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mFuel = PHYS_FUEL_INIT;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDX = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDY = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mHeading = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mEngineFiring = true;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Starts the game, setting parameters for the current difficulty.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void doStart() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // First set the game for Medium difficulty&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mFuel = PHYS_FUEL_INIT;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mEngineFiring = false;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalWidth = (int) (mLanderWidth * TARGET_WIDTH);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalSpeed = TARGET_SPEED;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalAngle = TARGET_ANGLE;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int speedInit = PHYS_SPEED_INIT;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Adjust difficulty params for EASY/HARD&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mDifficulty == DIFFICULTY_EASY) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mFuel = mFuel * 3 / 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalWidth = mGoalWidth * 4 / 3;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalSpeed = mGoalSpeed * 3 / 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalAngle = mGoalAngle * 4 / 3;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; speedInit = speedInit * 3 / 4;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else if (mDifficulty == DIFFICULTY_HARD) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mFuel = mFuel * 7 / 8;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalWidth = mGoalWidth * 3 / 4;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalSpeed = mGoalSpeed * 7 / 8;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; speedInit = speedInit * 4 / 3;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // pick a convenient initial location for the lander sprite&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mX = mCanvasWidth / 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mY = mCanvasHeight - mLanderHeight / 2;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // start with a little random motion&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDY = Math.random() * -speedInit;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDX = Math.random() * 2 * speedInit - speedInit;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mHeading = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Figure initial spot for landing, not too near center&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (true) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalX = (int) (Math.random() * (mCanvasWidth - mGoalWidth));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (Math.abs(mGoalX - (mX - mLanderWidth / 2)) &gt; mCanvasHeight / 6)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLastTime = System.currentTimeMillis() + 100;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setState(STATE_RUNNING);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Pauses the physics update &amp; animation.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void pause() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mMode == STATE_RUNNING) setState(STATE_PAUSE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Restores game state from the indicated Bundle. Typically called when&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * the Activity is being restored after having been previously&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * destroyed.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param savedState Bundle containing the game state&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public synchronized void restoreState(Bundle savedState) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setState(STATE_PAUSE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mRotating = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mEngineFiring = false;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDifficulty = savedState.getInt(KEY_DIFFICULTY);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mX = savedState.getDouble(KEY_X);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mY = savedState.getDouble(KEY_Y);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDX = savedState.getDouble(KEY_DX);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDY = savedState.getDouble(KEY_DY);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mHeading = savedState.getDouble(KEY_HEADING);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLanderWidth = savedState.getInt(KEY_LANDER_WIDTH);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mLanderHeight = savedState.getInt(KEY_LANDER_HEIGHT);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalX = savedState.getInt(KEY_GOAL_X);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalSpeed = savedState.getInt(KEY_GOAL_SPEED);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalAngle = savedState.getInt(KEY_GOAL_ANGLE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mGoalWidth = savedState.getInt(KEY_GOAL_WIDTH);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mWinsInARow = savedState.getInt(KEY_WINS);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mFuel = savedState.getDouble(KEY_FUEL);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (mRun) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Canvas c = null;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c = mSurfaceHolder.lockCanvas(null);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mMode == STATE_RUNNING) updatePhysics();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doDraw(c);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } finally {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // do this in a finally so that if an exception is thrown&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // during the above, we don't leave the Surface in an&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // inconsistent state&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (c != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mSurfaceHolder.unlockCanvasAndPost(c);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Dump game state to the provided Bundle. Typically called when the&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Activity is being suspended.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @return Bundle with this view's state&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Bundle saveState(Bundle map) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (map != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_DIFFICULTY, Integer.valueOf(mDifficulty));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putDouble(KEY_X, Double.valueOf(mX));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putDouble(KEY_Y, Double.valueOf(mY));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putDouble(KEY_DX, Double.valueOf(mDX));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putDouble(KEY_DY, Double.valueOf(mDY));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putDouble(KEY_HEADING, Double.valueOf(mHeading));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_LANDER_WIDTH, Integer.valueOf(mLanderWidth));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_LANDER_HEIGHT, Integer&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .valueOf(mLanderHeight));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_GOAL_X, Integer.valueOf(mGoalX));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_GOAL_SPEED, Integer.valueOf(mGoalSpeed));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_GOAL_ANGLE, Integer.valueOf(mGoalAngle));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_GOAL_WIDTH, Integer.valueOf(mGoalWidth));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putInt(KEY_WINS, Integer.valueOf(mWinsInARow));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.putDouble(KEY_FUEL, Double.valueOf(mFuel));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return map;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Sets the current difficulty.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param difficulty&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setDifficulty(int difficulty) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mDifficulty = difficulty;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Sets if the engine is currently firing.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setFiring(boolean firing) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mEngineFiring = firing;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Used to signal the thread whether it should be running or not.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Passing true allows the thread to run; passing false will shut it&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * down if it's already running. Calling start() after this was most&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * recently called with false will result in an immediate shutdown.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param b true to run, false to shut down&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setRunning(boolean b) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mRun = b;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Sets the game mode. That is, whether we are running, paused, in the&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * failure state, in the victory state, etc.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @see #setState(int, CharSequence)&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param mode one of the STATE_* constants&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setState(int mode) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setState(mode, null);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Sets the game mode. That is, whether we are running, paused, in the&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * failure state, in the victory state, etc.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param mode one of the STATE_* constants&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param message string to add to screen or null&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setState(int mode, CharSequence message) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * This method optionally can cause a text message to be displayed&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * to the user when the mode changes. Since the View that actually&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * renders that text is part of the main View hierarchy and not&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * owned by this thread, we can't touch the state of that View.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * Instead we use a Message + Handler to relay commands to the main&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * thread, which updates the user-text View.&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mMode = mode;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mMode == STATE_RUNNING) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Message msg = mHandler.obtainMessage();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle b = new Bundle();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.putString("text", "");&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.putInt("viz", View.INVISIBLE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.setData(b);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mHandler.sendMessage(msg);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mRotating = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mEngineFiring = false;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Resources res = mContext.getResources();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CharSequence str = "";&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mMode == STATE_READY)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str = res.getText(R.string.mode_ready);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (mMode == STATE_PAUSE)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str = res.getText(R.string.mode_pause);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (mMode == STATE_LOSE)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str = res.getText(R.string.mode_lose);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if (mMode == STATE_WIN)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str = res.getString(R.string.mode_win_prefix)&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + mWinsInARow + " "&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + res.getString(R.string.mode_win_suffix);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (message != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str = message + "\n" + str;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mMode == STATE_LOSE) mWinsInARow = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Message msg = mHandler.obtainMessage();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle b = new Bundle();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.putString("text", str.toString());&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.putInt("viz", View.VISIBLE);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; msg.setData(b);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mHandler.sendMessage(msg);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* Callback invoked when the surface dimensions change. */&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void setSurfaceSize(int width, int height) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // synchronized to make sure these all change atomically&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; synchronized (mSurfaceHolder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mCanvasWidth = width;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mCanvasHeight = height;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // don't forget to resize the background image&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mBackgroundImage = mBackgroundImage.createScaledBitmap(&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mBackgroundImage, width, height, true);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034565.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:21 <a href="http://www.blogjava.net/kissyan4916/articles/339688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（六）自定义View </title><link>http://www.blogjava.net/kissyan4916/articles/339685.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339685.html</guid><description><![CDATA[<p>有关Android的自定义 View 的框架今天我们一起讨论下，对于常规的游戏 ，我们在View中需要处理以下几种问题: 1.控制事件 2.刷新View 3. 绘制View。（文/Android开发 网）</p>
<p>&nbsp; 1. 对于控制事件今天我们只处理按键事件onKeyDown，以后的文章中将会讲到屏幕 触控的具体处理onTouchEvent以及Sensor重力感应等方法。</p>
<p>&nbsp; 2. 刷新view的方法这里主要有invalidate(int l, int t, int r, int b) 刷新局部，四个参数分别为左、上、右、下。整个view刷新 invalidate()，刷新一个矩形区域 invalidate(Rect dirty) ，刷新一个特性Drawable， invalidateDrawable(Drawable drawable) ，执行invalidate类的方法将会设置 view为无效，最终导致onDraw方法被重新调用。由于今天的view比较简单，Android123提示大家如果在线程中刷新，除了使用handler方式外，可以在Thread中直接使用postInvalidate方法来实现。</p>
<p>&nbsp; 3. 绘制View主要是onDraw()中通过形参canvas来处理，相关的绘制主要有drawRect、drawLine、drawPath等等。 view方法内部还重写了很多接口，其回调方法可以帮助我们判断出view的位置和大小，比如onMeasure(int, int) Called to determine the size requirements for this view and all of its children.&nbsp; 、onLayout(boolean, int, int, int, int) Called when this view should assign a size and position to all of its children 和onSizeChanged(int, int, int, int) Called when the size of this view has changed. 具体的作用，大家可以用Logcat获取 当view变化时每个形参的变动。</p>
<p>&nbsp; 下面cwjView是我们为今后游戏设计的一个简单自定义View框架，我们可以看到在Android平台 自定义view还是很简单的，同时Java 支持多继承可以帮助我们不断的完善复杂的问题。</p>
<p>view plaincopy to clipboardprint?<br />
public class cwjView extends View {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public cwjView(Context context) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setFocusable(true); //允许获得焦点&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setFocusableInTouchMode(true); //获取焦点时允许触控&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected Parcelable onSaveInstanceState() {&nbsp; //处理窗口保存事件&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Parcelable pSaved = super.onSaveInstanceState();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = new Bundle();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; //dosomething&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bundle;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected void onRestoreInstanceState(Parcelable state) {&nbsp; //处理窗口还原事件&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = (Bundle) state;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; //dosomething&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; super.onRestoreInstanceState(bundle.getParcelable("cwj"));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override&nbsp; <br />
&nbsp; protected void onSizeChanged(int w, int h, int oldw, int oldh) //处理窗口大小变化事件&nbsp;&nbsp; <br />
&nbsp; {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onSizeChanged(w, h, oldw, oldh);&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onMeasure(widthMeasureSpec, heightMeasureSpec); //如果不让父类处理记住调用setMeasuredDimension&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected void onLayout (boolean changed, int left, int top, int right, int bottom)&nbsp;&nbsp; <br />
&nbsp; {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; super.onLayout (changed,left,top, ight,bottom) ;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected void onDraw(Canvas canvas) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Paint bg = new Paint();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bg.setColor(Color.Red);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; canvas.drawRect(0, 0, getWidth()/2, getHeight()/2, bg); //将view的左上角四分之一填充为红色&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; public boolean onTouchEvent(MotionEvent event) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onTouchEvent(event); //让父类处理屏幕触控事件&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; public boolean onKeyDown(int keyCode, KeyEvent event) { //处理按键事件，响应的轨迹球事件为 public boolean onTrackballEvent (MotionEvent event)&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (keyCode) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_UP:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_DOWN:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_LEFT:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_RIGHT:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_CENTER: //处理中键按下&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onKeyDown(keyCode, event);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
}&nbsp; <br />
public class cwjView extends View {<br />
&nbsp;&nbsp;&nbsp; public cwjView(Context context) {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context);<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setFocusable(true); //允许获得焦点<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setFocusableInTouchMode(true); //获取焦点时允许触控<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; protected Parcelable onSaveInstanceState() {&nbsp; //处理窗口保存事件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Parcelable pSaved = super.onSaveInstanceState();<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = new Bundle();<br />
&nbsp;&nbsp;&nbsp; //dosomething<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bundle;<br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; protected void onRestoreInstanceState(Parcelable state) {&nbsp; //处理窗口还原事件<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = (Bundle) state;<br />
&nbsp;&nbsp;&nbsp; //dosomething<br />
&nbsp;&nbsp;&nbsp; super.onRestoreInstanceState(bundle.getParcelable("cwj"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp; protected void onSizeChanged(int w, int h, int oldw, int oldh) //处理窗口大小变化事件<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onSizeChanged(w, h, oldw, oldh);<br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)&nbsp; <br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onMeasure(widthMeasureSpec, heightMeasureSpec); //如果不让父类处理记住调用setMeasuredDimension<br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; protected void onLayout (boolean changed, int left, int top, int right, int bottom)<br />
&nbsp; {<br />
&nbsp;&nbsp;&nbsp; super.onLayout (changed,left,top, ight,bottom) ;<br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; protected void onDraw(Canvas canvas) {<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Paint bg = new Paint();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bg.setColor(Color.Red);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; canvas.drawRect(0, 0, getWidth()/2, getHeight()/2, bg); //将view的左上角四分之一填充为红色&nbsp; <br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; public boolean onTouchEvent(MotionEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onTouchEvent(event); //让父类处理屏幕触控事件<br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; public boolean onKeyDown(int keyCode, KeyEvent event) { //处理按键事件，响应的轨迹球事件为 public boolean onTrackballEvent (MotionEvent event) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (keyCode) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_UP:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_DOWN:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_LEFT:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_RIGHT:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_CENTER: //处理中键按下<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onKeyDown(keyCode, event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp; }<br />
} </p>
<p>上面我们可以看到onMeasure使用的是父类的处理方法，如果我们需要解决 自定义View的大小，可以尝试下面的方法</p>
<p>view plaincopy to clipboardprint?<br />
@Override&nbsp; <br />
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)&nbsp;&nbsp;&nbsp;&nbsp; <br />
{&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; height = View.MeasureSpec.getSize(heightMeasureSpec);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; width = View.MeasureSpec.getSize(widthMeasureSpec);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; setMeasuredDimension(width,height);&nbsp; //这里面是原始的大小，需要重新计算可以修改本行&nbsp;&nbsp; <br />
&nbsp; //dosomething&nbsp;&nbsp; <br />
}&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034560.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339685.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:20 <a href="http://www.blogjava.net/kissyan4916/articles/339685.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（七）自定义SurfaceView </title><link>http://www.blogjava.net/kissyan4916/articles/339687.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:20:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339687.html</guid><description><![CDATA[<p>今天我们说下未来的Android游戏 引擎模板架构问题，对于游戏我们还是选择SurfaceView ，相关的原因Android123已经在Android游戏开发 之旅 二 View和SurfaceView中说的很清楚了，这里我们直接继承SurfaceView，实现 SurfaceHolder.Callback接口，处理surfaceCreated、surfaceChanged以及 surfaceDestroyed方法，这里我们并没有把按键控制传入，最终游戏的控制方面仍然由View内部类处理比较好，有关SurfaceView 的具体我们可以参见Android开源项目 的Camera中有关画面捕捉以及VideoView的控件 实现大家可以清晰了解最终的用意。</p>
<p>view plaincopy to clipboardprint?<br />
public class cwjView extends SurfaceView implements SurfaceHolder.Callback {&nbsp;&nbsp; <br />
public cwjView(Context context, AttributeSet attrs) {&nbsp;&nbsp; <br />
&nbsp; super(context, attrs);&nbsp;&nbsp; <br />
&nbsp; SurfaceHolder holder=getHolder();&nbsp;&nbsp; <br />
&nbsp; holder.addCallback(this);&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; setFocusable(true);&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
public void surfaceCreated(SurfaceHolder holder) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
public void surfaceDestroyed(SurfaceHolder holder) {&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
@Override&nbsp; <br />
public void onWindowFocusChanged(boolean hasWindowFocus) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
}&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034562.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339687.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:20 <a href="http://www.blogjava.net/kissyan4916/articles/339687.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（五）Path和Typeface </title><link>http://www.blogjava.net/kissyan4916/articles/339684.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:19:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339684.html</guid><description><![CDATA[<p>今天我们继续处理上次 Android游戏 开发 之旅 （四）Canvas和Paint实例 中提到的Path路径和Typeface字体两个类。对于Android游戏开发或者说2D绘图中来讲Path 路径可以用强大这个词来形容。在Photoshop中我们可能还记得使用钢笔工具绘制路径的方法。Path路径类在位于 android .graphics.Path中，Path的构造方法比较简单，如下</p>
<p>view plaincopy to clipboardprint?<br />
Path cwj=new Path();&nbsp; //构造方法&nbsp; <br />
Path cwj=new Path();&nbsp; //构造方法 </p>
<p>下面我们画一个封闭的原型路径，我们使用Path类的addCircle方法</p>
<p>view plaincopy to clipboardprint?<br />
cwj.addCircle(10,10,50,Direction.CW); //参数一为x轴水平位置，参数二为y轴垂直位置，第三个参数为圆形的半径，最后是绘制的方向，CW为顺时针方向，而CCW是逆时针方向&nbsp; <br />
cwj.addCircle(10,10,50,Direction.CW); //参数一为x轴水平位置，参数二为y轴垂直位置，第三个参数为圆形的半径，最后是绘制的方向，CW为顺时针方向，而CCW是逆时针方向 </p>
<p>结合Android上次提到的Canvas类中的绘制方法drawPath和drawTextOnPath，我们继续可以在onDraw中加入。</p>
<p>view plaincopy to clipboardprint?<br />
canvas.drawPath(cwj,paintPath); //Android123提示大家这里paintPath为路径的画刷颜色，可以见下文完整的源代码。&nbsp;&nbsp; <br />
canvas.drawTextOnPath("Android123 - CWJ",cwj,0,15,paintText); //将文字绘制到路径中去，&nbsp; <br />
canvas.drawPath(cwj,paintPath); //Android123提示大家这里paintPath为路径的画刷颜色，可以见下文完整的源代码。<br />
canvas.drawTextOnPath("Android123 - CWJ",cwj,0,15,paintText); //将文字绘制到路径中去， </p>
<p>有关drawTextOnPath的参数如下:</p>
<p>方法原型</p>
<p>view plaincopy to clipboardprint?<br />
public void drawTextOnPath (String text, Path path, float hOffset, float vOffset, Paint paint)&nbsp; <br />
public void drawTextOnPath (String text, Path path, float hOffset, float vOffset, Paint paint) </p>
<p>参数列表</p>
<p>text&nbsp; 为需要在路径上绘制的文字内容。<br />
path 将文字绘制到哪个路径。 <br />
hOffset&nbsp; 距离路径开始的距离<br />
vOffset&nbsp; 离路径的上下高度，这里Android开发网提示大家，该参数类型为float浮点型，除了精度为8位小数外，可以为正或负，当为正时文字在路径的圈里面，为负时在路径的圈外面。<br />
paint&nbsp; 最后仍然是一个Paint对象用于制定Text本文的颜色、字体、大小等属性。</p>
<p>下面是我们的onDraw方法中如何绘制路径的演示代码为:</p>
<p>view plaincopy to clipboardprint?<br />
@Override&nbsp; <br />
protected void onDraw(Canvas canvas) {&nbsp;&nbsp; <br />
&nbsp; Paint paintPath=new Paint();&nbsp;&nbsp; <br />
&nbsp; Paint paintText=new Paint();&nbsp;&nbsp; <br />
&nbsp; paintPath.setColor(Color.Red); //路径的画刷为红色&nbsp;&nbsp; <br />
&nbsp; paintText.setColor(Color.Blue); //路径上的文字为蓝色&nbsp;&nbsp; <br />
&nbsp; Path pathCWJ=new Path();&nbsp;&nbsp; <br />
&nbsp; pathCWJ.addCircle(10,10,50,Direction.CW); // 半径为50px，绘制的方向CW为顺时针&nbsp;&nbsp; <br />
&nbsp; canvas.drawPath(pathCWJ,paintPath);&nbsp;&nbsp; <br />
canvas.drawTextOnPath("Android123 - CWJ",pathCWJ,0,15,paintText); //在路径上绘制文字&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp; @Override<br />
&nbsp; protected void onDraw(Canvas canvas) {<br />
&nbsp;&nbsp;&nbsp; Paint paintPath=new Paint();<br />
&nbsp;&nbsp;&nbsp; Paint paintText=new Paint();<br />
&nbsp;&nbsp;&nbsp; paintPath.setColor(Color.Red); //路径的画刷为红色<br />
&nbsp;&nbsp;&nbsp; paintText.setColor(Color.Blue); //路径上的文字为蓝色<br />
&nbsp;&nbsp;&nbsp; Path pathCWJ=new Path();<br />
&nbsp;&nbsp;&nbsp; pathCWJ.addCircle(10,10,50,Direction.CW); // 半径为50px，绘制的方向CW为顺时针<br />
&nbsp;&nbsp;&nbsp; canvas.drawPath(pathCWJ,paintPath);<br />
&nbsp; canvas.drawTextOnPath("Android123 - CWJ",pathCWJ,0,15,paintText); //在路径上绘制文字<br />
&nbsp; } </p>
<p>有关路径类常用的方法如下:</p>
<p>view plaincopy to clipboardprint?<br />
void&nbsp; addArc(RectF oval, float startAngle, float sweepAngle)&nbsp; //为路径添加一个多边形&nbsp;&nbsp; <br />
void&nbsp; addCircle(float x, float y, float radius, Path.Direction dir)&nbsp; //给path添加圆圈&nbsp;&nbsp; <br />
void&nbsp; addOval(RectF oval, Path.Direction dir)&nbsp; //添加椭圆形&nbsp;&nbsp; <br />
void&nbsp; addRect(RectF rect, Path.Direction dir)&nbsp; //添加一个区域&nbsp;&nbsp; <br />
void&nbsp; addRoundRect(RectF rect, float[] radii, Path.Direction dir)&nbsp; //添加一个圆角区域&nbsp;&nbsp; <br />
boolean&nbsp; isEmpty()&nbsp; //判断路径是否为空&nbsp;&nbsp; <br />
void&nbsp; transform(Matrix matrix)&nbsp; //应用矩阵变换&nbsp;&nbsp; <br />
void&nbsp; transform(Matrix matrix, Path dst)&nbsp; //应用矩阵变换并将结果放到新的路径中，即第二个参数。&nbsp; <br />
void&nbsp; addArc(RectF oval, float startAngle, float sweepAngle)&nbsp; //为路径添加一个多边形<br />
void&nbsp; addCircle(float x, float y, float radius, Path.Direction dir)&nbsp; //给path添加圆圈<br />
void&nbsp; addOval(RectF oval, Path.Direction dir)&nbsp; //添加椭圆形<br />
void&nbsp; addRect(RectF rect, Path.Direction dir)&nbsp; //添加一个区域<br />
void&nbsp; addRoundRect(RectF rect, float[] radii, Path.Direction dir)&nbsp; //添加一个圆角区域<br />
boolean&nbsp; isEmpty()&nbsp; //判断路径是否为空<br />
void&nbsp; transform(Matrix matrix)&nbsp; //应用矩阵变换<br />
void&nbsp; transform(Matrix matrix, Path dst)&nbsp; //应用矩阵变换并将结果放到新的路径中，即第二个参数。 </p>
<p>有关路径的高级效果 大家可以使用PathEffect类，有关路径的更多实例Android123将在今后的游戏开发实战中讲解道。</p>
<p>Typeface字体类</p>
<p>平时我们在TextView 中需要设置 显示的字体可以通过TextView 中的setTypeface方法来指定一个Typeface对象，因为 Android的字体类比较简单，我们列出所有成员方法</p>
<p>view plaincopy to clipboardprint?<br />
static Typeface&nbsp; create(Typeface family, int style)&nbsp; //静态方法，参数一为字体类型这里是Typeface的静态定义，如宋体，参数二风格，如粗体，斜体&nbsp;&nbsp; <br />
static Typeface&nbsp; create(String familyName, int style)&nbsp; //静态方法，参数一为字体名的字符串，参数二为风格同上，这里我们推荐使用上面的方法。&nbsp;&nbsp; <br />
static Typeface&nbsp; createFromAsset(AssetManager mgr, String path)&nbsp; //静态方法，参数一为AssetManager对象，主要用于从APK的assets文件夹中取出字体，参数二为相对于Android工程下的 assets文件夹中的外挂字体文件的路径。&nbsp;&nbsp; <br />
static Typeface&nbsp; createFromFile(File path)&nbsp; //静态方法，从文件系统构造一个字体，这里参数可以是sdcard中的某个字体文件&nbsp;&nbsp; <br />
static Typeface&nbsp; createFromFile(String path)&nbsp; //静态方法，从指定路径中构造字体&nbsp;&nbsp; <br />
static Typeface&nbsp; defaultFromStyle(int style) //静态方法，返回默认的字体风格&nbsp;&nbsp; <br />
int&nbsp; getStyle()&nbsp; //获取当前字体风格&nbsp;&nbsp; <br />
final boolean&nbsp; isBold()&nbsp; //判断当前是否为粗体&nbsp;&nbsp; <br />
final boolean&nbsp; isItalic()&nbsp; //判断当前风格是否为斜体&nbsp; <br />
static Typeface&nbsp; create(Typeface family, int style)&nbsp; //静态方法，参数一为字体类型这里是Typeface的静态定义，如宋体，参数二风格，如粗体，斜体<br />
static Typeface&nbsp; create(String familyName, int style)&nbsp; //静态方法，参数一为字体名的字符串，参数二为风格同上，这里我们推荐使用上面的方法。<br />
static Typeface&nbsp; createFromAsset(AssetManager mgr, String path)&nbsp; //静态方法，参数一为AssetManager对象，主要用于从APK的assets文件夹中取出字体，参数二为相对于Android工程下的 assets文件夹中的外挂字体文件的路径。<br />
static Typeface&nbsp; createFromFile(File path)&nbsp; //静态方法，从文件系统构造一个字体，这里参数可以是sdcard中的某个字体文件<br />
static Typeface&nbsp; createFromFile(String path)&nbsp; //静态方法，从指定路径中构造字体<br />
static Typeface&nbsp; defaultFromStyle(int style) //静态方法，返回默认的字体风格<br />
int&nbsp; getStyle()&nbsp; //获取当前字体风格<br />
final boolean&nbsp; isBold()&nbsp; //判断当前是否为粗体<br />
final boolean&nbsp; isItalic()&nbsp; //判断当前风格是否为斜体 </p>
<p>本类的常量静态定义，首先为字体类型名称</p>
<p>Typeface DEFAULT <br />
Typeface DEFAULT_BOLD<br />
Typeface MONOSPACE<br />
Typeface SANS_SERIF<br />
Typeface SERIF</p>
<p>字体风格名称</p>
<p>int BOLD <br />
int BOLD_ITALIC <br />
int ITALIC<br />
int NORMAL</p>
<p>明天我们将在 Android游戏开发之旅 六 自定义View 一文中具体讲解onDraw以及什么时候会触发绘制方法，来实现我们自定义或子类化控件 。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034555.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339684.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:19 <a href="http://www.blogjava.net/kissyan4916/articles/339684.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（四）Canvas和Paint实例 </title><link>http://www.blogjava.net/kissyan4916/articles/339683.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339683.html</guid><description><![CDATA[<p>昨天我们在Android游戏 开发 之旅 （三）View 类详解中提到了onDraw方法，有关详细的实现我们今天主要说下Android的Canvas和Paint对象的使用实例。</p>
<p>Canvas类主要实现了屏幕 的绘制过程，其中包含了很多实用的方法，比如绘制一条路径、区域、贴图、画点、画线、渲染文本，下面是Canvas类常用的方法，当然Android开发网提示大家很多方法有不同的重载版本，参数更灵活。</p>
<p>void drawRect(RectF rect, Paint paint) //绘制区域，参数一为RectF一个区域</p>
<p>void drawPath(Path path, Paint paint) //绘制一个路径，参数一为Path路径对象 </p>
<p>void&nbsp; drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)&nbsp; //贴图，参数一就是我们常规的Bitmap对象，参数二是源区域(Android123提示这里是bitmap)，参数三是目标区域 (应该在 canvas的位置和大小)，参数四是Paint画刷对象，因为用到了缩放和拉伸的可能，当原始Rect不等于目标Rect时性能将会有大幅损失。 </p>
<p>void&nbsp; drawLine(float startX, float startY, float stopX, float stopY, Paint paint)&nbsp; //画线，参数一起始点的x轴位置，参数二起始点的y轴位置，参数三终点的x轴水平位置，参数四y轴垂直位置，最后一个参数为Paint 画刷对象。</p>
<p>void&nbsp; drawPoint(float x, float y, Paint paint) //画点，参数一水平x轴，参数二垂直y轴，第三个参数为Paint对象。</p>
<p>void drawText(String text, float x, float y, Paint paint)&nbsp; //渲染文本，Canvas类除了上面的还可以描绘文字，参数一是String类型的文本，参数二x轴，参数三y轴，参数四是Paint对象。</p>
<p>void&nbsp; drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint) //在路径上绘制文本，相对于上面第二个参数是Path路径对象</p>
<p>从上面来看我们可以看出Canvas绘制类比较简单同时很灵活，实现一般的方法通常没有问题，同时可以叠加的处理设计出一些效果 ，不过细心的网友可能发现最后一个参数均为Paint对象。如果我们把Canvas当做绘画师来看，那么Paint就是我们绘画的工具，比如画笔、画刷、颜料等等。</p>
<p>Paint类常用方法:</p>
<p>void&nbsp; setARGB(int a, int r, int g, int b)&nbsp; 设置 Paint对象颜色，参数一为alpha透明通道</p>
<p>void&nbsp; setAlpha(int a)&nbsp; 设置alpha不透明度，范围为0~255</p>
<p>void&nbsp; setAntiAlias(boolean aa)&nbsp; //是否抗锯齿</p>
<p>void&nbsp; setColor(int color)&nbsp; //设置颜色，这里Android内部定义 的有Color类包含了一些常见颜色定义</p>
<p>void&nbsp; setFakeBoldText(boolean fakeBoldText)&nbsp; //设置伪粗体文本<br />
&nbsp; <br />
void&nbsp; setLinearText(boolean linearText)&nbsp; //设置线性文本</p>
<p>PathEffect&nbsp; setPathEffect(PathEffect effect)&nbsp; //设置路径效果</p>
<p>Rasterizer&nbsp; setRasterizer(Rasterizer rasterizer) //设置光栅化</p>
<p>Shader&nbsp; setShader(Shader shader)&nbsp; //设置阴影 </p>
<p>void&nbsp; setTextAlign(Paint.Align align)&nbsp; //设置文本对齐</p>
<p>void&nbsp; setTextScaleX(float scaleX)&nbsp; //设置文本缩放倍数，1.0f为原始</p>
<p>void&nbsp; setTextSize(float textSize)&nbsp; //设置字体大小</p>
<p>Typeface&nbsp; setTypeface(Typeface typeface)&nbsp; //设置字体，Typeface包含了字体的类型，粗细，还有倾斜、颜色等。</p>
<p>void&nbsp; setUnderlineText(boolean underlineText)&nbsp; //设置下划线</p>
<p>最终 Canvas和Paint在onDraw中直接使用</p>
<p>view plaincopy to clipboardprint?<br />
@Override&nbsp; <br />
&nbsp; protected void onDraw(Canvas canvas) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; Paint paintRed=new Paint();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; paintRed.setColor(Color.Red);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; canvas.drawPoint(11,3,paintRed); //在坐标11,3上画一个红点&nbsp;&nbsp; <br />
&nbsp; }&nbsp; </p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034545.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:18 <a href="http://www.blogjava.net/kissyan4916/articles/339683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（三）View类详解</title><link>http://www.blogjava.net/kissyan4916/articles/339682.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:17:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339682.html</guid><description><![CDATA[<p>&nbsp; 在Android游戏 开发 之旅 二中我们讲到了View 和SurfaceView的区别，今天Android123从View类开始着重的介绍 Android图形显示基类的相关方法和注意点。（文/Android开发网）</p>
<p>自定义 View的常用方法:</p>
<p>onFinishInflate() 当View中所有的子控件 均被映射成xml后触发</p>
<p>onMeasure(int, int) 确定所有子元素的大小</p>
<p>onLayout(boolean, int, int, int, int) 当View分配所有的子元素的大小和位置时触发</p>
<p>onSizeChanged(int, int, int, int) 当view的大小发生变化时触发</p>
<p>onDraw(Canvas) view渲染内容的细节</p>
<p>onKeyDown(int, KeyEvent) 有按键按下后触发</p>
<p>onKeyUp(int, KeyEvent) 有按键按下后弹起时触发</p>
<p>onTrackballEvent(MotionEvent) 轨迹球事件</p>
<p>onTouchEvent(MotionEvent) 触屏事件</p>
<p>onFocusChanged(boolean, int, Rect) 当View获取 或失去焦点时触发 </p>
<p>onWindowFocusChanged(boolean) 当窗口包含的view获取或失去焦点时触发</p>
<p>onAttachedToWindow() 当view被附着到一个窗口时触发</p>
<p>onDetachedFromWindow() 当view离开附着的窗口时触发，Android123提示该方法和&nbsp; onAttachedToWindow() 是相反的。</p>
<p>onWindowVisibilityChanged(int) 当窗口中包含的可见的view发生变化时触发</p>
<p>&nbsp; 以上是View实现的一些基本接口的回调方法，一般我们需要处理画布的显示时，重写onDraw(Canvas)用的的是最多的：</p>
<p>view plaincopy to clipboardprint?<br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected void onDraw(Canvas canvas) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; //这里我们直接使用canvas对象处理当前的画布，比如说使用Paint来选择要填充的颜色&nbsp;&nbsp; <br />
&nbsp; Paint paintBackground = new Paint();&nbsp;&nbsp; <br />
&nbsp; paintBackground.setColor(getResources().getColor(R.color.xxx));&nbsp; //从Res中找到名为xxx的color颜色定义&nbsp;&nbsp; <br />
&nbsp; canvas.drawRect(0, 0, getWidth(), getHeight(), paintBackground); //设置当前画布的背景颜色为paintBackground中定义的颜色，以0,0作为为起点，以当前画布的宽度和高度为重点即整块画布来填充，具体的请查看Android123未来讲到的Canvas和Paint，在Canvas中我们可以实现画路径，图形，区域，线。而Paint作为绘画方式的对象可以设置颜色，大小，甚至字体的类型等等。&nbsp;&nbsp; <br />
}&nbsp; <br />
&nbsp; @Override<br />
&nbsp; protected void onDraw(Canvas canvas) {<br />
&nbsp;&nbsp;&nbsp; //这里我们直接使用canvas对象处理当前的画布，比如说使用Paint来选择要填充的颜色<br />
&nbsp; Paint paintBackground = new Paint();<br />
&nbsp; paintBackground.setColor(getResources().getColor(R.color.xxx));&nbsp; //从Res中找到名为xxx的color颜色定义<br />
&nbsp; canvas.drawRect(0, 0, getWidth(), getHeight(), paintBackground); //设置当前画布的背景颜色为paintBackground中定义的颜色，以0,0作为为起点，以当前画布的宽度和高度为重点即整块画布来填充，具体的请查看Android123未来讲到的Canvas和Paint，在Canvas中我们可以实现画路径，图形，区域，线。而Paint作为绘画方式的对象可以设置颜色，大小，甚至字体的类型等等。<br />
} </p>
<p>当然还有就是处理窗口还原状态问题(一般用于横竖屏切换)，除了在Activity中可以调用外，开发游戏时我们尽量在View中使用类似</p>
<p>view plaincopy to clipboardprint?<br />
@Override&nbsp; <br />
&nbsp; protected Parcelable onSaveInstanceState() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Parcelable p = super.onSaveInstanceState();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = new Bundle();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bundle.putInt("x", pX);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bundle.putInt("y", pY);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bundle.putParcelable("android123_state", p);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bundle;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; protected void onRestoreInstanceState(Parcelable state) {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = (Bundle) state;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dosomething(bundle.getInt("x"), bundle.getInt("y")); //获取刚才存储的x和y信息&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onRestoreInstanceState(bundle.getParcelable("android123_state"));&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;&nbsp;&nbsp; <br />
&nbsp; }&nbsp; <br />
@Override<br />
&nbsp; protected Parcelable onSaveInstanceState() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Parcelable p = super.onSaveInstanceState();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = new Bundle();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bundle.putInt("x", pX);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bundle.putInt("y", pY);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bundle.putParcelable("android123_state", p);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bundle;<br />
&nbsp; }<br />
&nbsp; @Override<br />
&nbsp; protected void onRestoreInstanceState(Parcelable state) { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bundle bundle = (Bundle) state;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dosomething(bundle.getInt("x"), bundle.getInt("y")); //获取刚才存储的x和y信息<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onRestoreInstanceState(bundle.getParcelable("android123_state"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br />
&nbsp; }</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034540.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339682.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:17 <a href="http://www.blogjava.net/kissyan4916/articles/339682.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android游戏开发之旅（二）View和SurfaceView</title><link>http://www.blogjava.net/kissyan4916/articles/339680.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:16:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339680.html</guid><description><![CDATA[<p>&nbsp;在Android游戏 当中充当主要的除了控制类外就是显示类，在J2ME中我们用Display和Canvas来实现这些，而Google Android中涉及到显示的为view类，Android游戏开发 中比较重要和复杂的就是显示和游戏逻辑的处理。这里我们说下 android .view.View 和android.view.SurfaceView。SurfaceView是从View基类中派生出来的显示类，直接子类有GLSurfaceView和VideoView，可以看出GL和视频 播放 以及Camera摄像头一般均使用SurfaceView，到底有哪些优势呢? SurfaceView可以控制表面的格式，比如大小，显示在屏幕 中的位置，最关键是的提供了SurfaceHolder类，使用getHolder方法获取 ，相关的有Canvas&nbsp; lockCanvas() <br />
Canvas&nbsp; lockCanvas(Rect dirty)&nbsp; 、void&nbsp; removeCallback(SurfaceHolder.Callback callback)、void&nbsp; unlockCanvasAndPost(Canvas canvas) 控制图形以及绘制，而在SurfaceHolder.Callback 接口回调中可以通过下面三个抽象类可以自己定义 具体的实现，比如第一个更改格式和显示画面。</p>
<p>view plaincopy to clipboardprint?<br />
abstract void&nbsp; surfaceChanged(SurfaceHolder holder, int format, int width, int height)&nbsp;&nbsp; <br />
abstract void&nbsp; surfaceCreated(SurfaceHolder holder)&nbsp;&nbsp; <br />
abstract void&nbsp; surfaceDestroyed(SurfaceHolder holder)&nbsp; <br />
abstract void&nbsp; surfaceChanged(SurfaceHolder holder, int format, int width, int height)<br />
abstract void&nbsp; surfaceCreated(SurfaceHolder holder)<br />
abstract void&nbsp; surfaceDestroyed(SurfaceHolder holder) </p>
<p>对于Surface相关的，Android底层还提供了GPU加速功能 ，所以一般实时性很强的应用 中主要使用SurfaceView而不是直接从View 构建，同时Android123未来后面说到的OpenGL中的GLSurfaceView也是从该类实现。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034536.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339680.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:16 <a href="http://www.blogjava.net/kissyan4916/articles/339680.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)Android游戏开发之旅（一）</title><link>http://www.blogjava.net/kissyan4916/articles/339677.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:05:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339677.html</guid><description><![CDATA[<p>今天Android123开始新的Android游戏 开发 之旅 系列，主要从控制方法(按键、轨迹球、触屏、重力感应、摄像头、话筒气流、光线亮度)、图形 View (高效绘图技术如双缓冲)、音效(游戏音乐)以及最后的OpenGL ES(Java 层)和NDK 的OpenGL和J2ME游戏移植 到Android方法，当然还有一些游戏实现惯用方法，比如地图编辑器，在Android OpenGL如何使用MD2文件 ，个部分讲述下Android游戏开发的过程最终实现一个比较完整的游戏引擎。相信大家都清楚Android Market下载 量比较好的都是游戏，未来手机 网游的发展相信Android使用的Java在这方面有比iPhone 有更低的入门 门槛。（文/Android开发网）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于很多游戏使用屏幕 控制一般需要考虑长按事件，比如在动作类的游戏中需要长按发射武器，结合Android Button模型，我们实现一个带图片的Button的长按，为了更清晰的显示原理，Android开发网这里使用ImageButton作为基类</p>
<p>view plaincopy to clipboardprint?<br />
public class RepeatingImageButton extends ImageButton {&nbsp;&nbsp; <br />
&nbsp; private long mStartTime; //记录长按开始&nbsp;&nbsp; <br />
&nbsp; private int mRepeatCount; //重复次数计数&nbsp;&nbsp; <br />
&nbsp; private RepeatListener mListener;&nbsp;&nbsp; <br />
&nbsp; private long mInterval = 500; //Timer触发间隔，即每0.5秒算一次按下&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; public RepeatingImageButton(Context context) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this(context, null);&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; public RepeatingImageButton(Context context, AttributeSet attrs) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this(context, attrs, android.R.attr.imageButtonStyle);&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; public RepeatingImageButton(Context context, AttributeSet attrs, int defStyle) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs, defStyle);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setFocusable(true); //允许获得焦点&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setLongClickable(true); //启用长按事件&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; public void setRepeatListener(RepeatListener l, long interval) { //实现重复按下事件listener&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mListener = l;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mInterval = interval;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; public boolean performLongClick() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mStartTime = SystemClock.elapsedRealtime();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mRepeatCount = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post(mRepeater);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; public boolean onTouchEvent(MotionEvent event) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event.getAction() == MotionEvent.ACTION_UP) {&nbsp; //&nbsp; 本方法原理同onKeyUp的一样，这里处理屏幕事件，下面的onKeyUp处理Android手机上的物理按键事件&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; removeCallbacks(mRepeater);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mStartTime != 0) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doRepeat(true);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mStartTime = 0;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onTouchEvent(event);&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
//处理导航键事件的中键或轨迹球按下事件&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; public boolean onKeyDown(int keyCode, KeyEvent event) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (keyCode) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_CENTER:&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_ENTER:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onKeyDown(keyCode, event);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onKeyDown(keyCode, event);&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
//当按键弹起通知长按结束&nbsp;&nbsp; <br />
&nbsp; @Override&nbsp; <br />
&nbsp; public boolean onKeyUp(int keyCode, KeyEvent event) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (keyCode) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_CENTER:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_ENTER:&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; removeCallbacks(mRepeater); //取消重复listener捕获&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mStartTime != 0) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doRepeat(true); //如果长按事件累计时间不为0则说明长按了&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mStartTime = 0; //重置长按计时器&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onKeyUp(keyCode, event);&nbsp;&nbsp; <br />
&nbsp; }&nbsp;&nbsp; <br />
&nbsp; <br />
&nbsp; private Runnable mRepeater = new Runnable() {&nbsp; //在线程中判断重复&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doRepeat(false);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isPressed()) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; postDelayed(this, mInterval); //计算长按后延迟下一次累加&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; };&nbsp;&nbsp; <br />
&nbsp; private&nbsp; void doRepeat(boolean last) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long now = SystemClock.elapsedRealtime();&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mListener != null) {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mListener.onRepeat(this, now - mStartTime, last ? -1 : mRepeatCount++);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br />
&nbsp; }&nbsp; <br />
&nbsp; public class RepeatingImageButton extends ImageButton {<br />
&nbsp;&nbsp;&nbsp; private long mStartTime; //记录长按开始<br />
&nbsp;&nbsp;&nbsp; private int mRepeatCount; //重复次数计数<br />
&nbsp;&nbsp;&nbsp; private RepeatListener mListener;<br />
&nbsp;&nbsp;&nbsp; private long mInterval = 500; //Timer触发间隔，即每0.5秒算一次按下<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public RepeatingImageButton(Context context) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this(context, null);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public RepeatingImageButton(Context context, AttributeSet attrs) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this(context, attrs, android.R.attr.imageButtonStyle);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public RepeatingImageButton(Context context, AttributeSet attrs, int defStyle) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super(context, attrs, defStyle);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setFocusable(true); //允许获得焦点<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setLongClickable(true); //启用长按事件<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public void setRepeatListener(RepeatListener l, long interval) { //实现重复按下事件listener<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mListener = l;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mInterval = interval;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public boolean performLongClick() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mStartTime = SystemClock.elapsedRealtime();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mRepeatCount = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; post(mRepeater);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public boolean onTouchEvent(MotionEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (event.getAction() == MotionEvent.ACTION_UP) {&nbsp; //&nbsp; 本方法原理同onKeyUp的一样，这里处理屏幕事件，下面的onKeyUp处理Android手机上的物理按键事件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; removeCallbacks(mRepeater); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mStartTime != 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doRepeat(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mStartTime = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onTouchEvent(event);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; //处理导航键事件的中键或轨迹球按下事件<br />
&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public boolean onKeyDown(int keyCode, KeyEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (keyCode) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_CENTER: <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_ENTER:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; super.onKeyDown(keyCode, event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onKeyDown(keyCode, event);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; //当按键弹起通知长按结束<br />
&nbsp;&nbsp;&nbsp; @Override<br />
&nbsp;&nbsp;&nbsp; public boolean onKeyUp(int keyCode, KeyEvent event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (keyCode) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_DPAD_CENTER:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case KeyEvent.KEYCODE_ENTER:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; removeCallbacks(mRepeater); //取消重复listener捕获<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mStartTime != 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doRepeat(true); //如果长按事件累计时间不为0则说明长按了<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mStartTime = 0; //重置长按计时器<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return super.onKeyUp(keyCode, event);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp; <br />
&nbsp;&nbsp;&nbsp; private Runnable mRepeater = new Runnable() {&nbsp; //在线程中判断重复<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doRepeat(false);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (isPressed()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; postDelayed(this, mInterval); //计算长按后延迟下一次累加<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; };<br />
&nbsp;&nbsp;&nbsp; private&nbsp; void doRepeat(boolean last) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long now = SystemClock.elapsedRealtime();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (mListener != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mListener.onRepeat(this, now - mStartTime, last ? -1 : mRepeatCount++);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; } </p>
<p>下面是重复Button Listener接口的定义 ，调用时在Button中先使用setRepeatListener()方法实现RepeatListener接口</p>
<p>view plaincopy to clipboardprint?<br />
public interface RepeatListener {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void onRepeat(View v, long duration, int repeatcount); //参数一为用户传入的Button对象，参数二为延迟的毫秒数，第三位重复次数回调。&nbsp;&nbsp; <br />
}&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; public interface RepeatListener {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void onRepeat(View v, long duration, int repeatcount); //参数一为用户传入的Button对象，参数二为延迟的毫秒数，第三位重复次数回调。<br />
&nbsp;&nbsp;&nbsp; }<br />
} </p>
<p>本类大家可以直接在自己的View中implements实现RepeatListener接口即可。</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/JavaTiger427/archive/2010/11/25/6034526.aspx</p><img src ="http://www.blogjava.net/kissyan4916/aggbug/339677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:05 <a href="http://www.blogjava.net/kissyan4916/articles/339677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android SDK中tools详解（转）</title><link>http://www.blogjava.net/kissyan4916/articles/339676.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Fri, 03 Dec 2010 02:02:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339676.html</guid><description><![CDATA[Android SDK包含了各种各样的定制工具，简介如下：<br />
Android<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E6%A8%A1%E6%8B%9F">模拟</span>器（Android Emulator ）<br />
它是在你的计算机上<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E8%BF%90%E8%A1%8C">运行</span>的一个虚拟移动设备。你可以使用模拟器来在一个实际的Android运行<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E7%8E%AF%E5%A2%83">环境</span>下设计，<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E8%B0%83%E8%AF%95">调试</span>和测试你的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E5%BA%94%E7%94%A8">应用</span><span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E7%A8%8B%E5%BA%8F">程序</span>。<br />
Android调试桥（Android Debug Bridge (adb) ）<br />
Adb 工具可以让你在模拟器或设备上安装<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F">应用程序</span>的.apk<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E6%96%87%E4%BB%B6">文件</span>，并从命令行访问模拟器或设备。你也可以用它把Android模拟器或设备上的应用程序<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E4%BB%A3%E7%A0%81">代码</span>和一个标准的调试器连接在一起。<br />
层级观察器 （Hierarchy <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=View">View</span>er ）<br />
层级观察器工具允许你调试和优化你的用户<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E7%95%8C%E9%9D%A2">界面</span>。它用可视的方法把你的视图（view）的布局层次展现出来，<br />
此外还给当前界面提供了一个具有像素栅格(grid)的放大镜观察器，这样你就可以正确地布局了。<br />
9-patch<br />
Draw 9-patch工具允许你使用所见即所得（WYSIWYG）的编辑器轻松地创建NinePatch图形。它也可以预览经过拉伸的图像，高亮显示内容区域。<br />
<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=Eclipse">Eclipse</span> IDE Android <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E5%BC%80%E5%8F%91">开发</span>工具插件（Android Development Tools Plugin for the Eclipse IDE）<br />
ADT插件大大扩展了Eclipse集成环境<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E5%8A%9F%E8%83%BD">功能</span>，使得生成和调试你的Android应用程序既容易又迅速。如果你使用Eclipse，ADT插件可以让你难以置信地加快开发Android应用程序的 速度。<br />
你可以从Eclipse IDE内部访问其它Android开发工具。例如，ADT可以让你直接从Eclipse访问DDMS工具的很多功能—<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E5%B1%8F%E5%B9%95">屏幕</span>截图，管理端口转发（port-forwarding）,<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E8%AE%BE%E7%BD%AE">设置</span>断点，观察线程和进程信息。<br />
它提供了一个新的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E9%A1%B9%E7%9B%AE">项目</span>向导（New Project Wizard），帮助你快速生成和建立起新Android应用程序所需的最基本的文件。<br />
它使得构建Android应用程序的过程变得<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E8%87%AA%E5%8A%A8">自动</span>化以及简单易行。<br />
它提供了一个<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=android">android</span>代码编辑器，可以帮助你为Android manifest和资源文件编写有效的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=XML">XML</span>。<br />
有关ADT插件的更多详细信息，包括安装指令，可参考Android 开发环境安装。如果你想看一个用法范例的屏幕截图，可参考Hello Android。<br />
Dalvik 调试监视器服务（Dalvik Debug Monitor <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=Service">Service</span> (ddms)）<br />
这个工具集成了Dalvik（为Android <span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E5%B9%B3%E5%8F%B0">平台</span>定制的虚拟机（VM）），能够让你在模拟器或者设备上管理进程并协助调试。你可以使用它杀死进程，选择某个特定的进程来调试，产生跟踪<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E6%95%B0%E6%8D%AE">数据</span>，观察堆（heap）和线程信息，截取模拟器或设备的屏幕画面，还有更多的功能。<br />
Android Asset Packaging Tool (aapt)<br />
Aapt工具可以让你创建包含Android应用程序二进制文件和资源文件的.apk文件。<br />
Android接口描述语言（Android Interface Description Language (aidl)）<br />
可以让你生成进程间的接口的代码，诸如service可能使用的接口。<br />
sqlite3<br />
这个工具能够让你方便地访问<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=SQLite">SQLite</span> 数据文件。这些数据文件是由Android 应用程序创建并使用的。<br />
Traceview<br />
这个工具可以将你的Android 应用程序产生的跟踪日志（trace log）转换为图形化的分析视图。<br />
mksdcard<br />
帮助你创建磁盘映像（disk image），你可以在模拟器环境下使用磁盘映像来模拟外部存储卡（例如SD 卡）。<br />
dx<br />
Dx gongju 将.class字节码（bytecode）转换为Android字节码（保存在.dex文件中） 。<br />
UI/Application Exerciser Monkey<br />
Monkey是在模拟器上或设备上运行的一个小程序，它能够产生为随机的用户事件流，例如点击(click)，触摸(touch)，挥手（gestures），还有一系列的<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E7%B3%BB%E7%BB%9F">系统</span>级事件。你可以使用Monkey来给你正在开发的程序做随机的，但可重复的压力测试 。<br />
<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=activity">activity</span>creator<br />
一个可以产生Ant build 文件的脚本，你可以使用它<span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%E7%BC%96%E8%AF%91">编译</span>你的android 应用程序。如果你正在Eclipse上开发，并使用ADT插件，你不必使用这个脚本。<br />
转载自<a href="http://android.hk.cn/" target="_blank">http://android.hk.cn</a><img src ="http://www.blogjava.net/kissyan4916/aggbug/339676.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-03 10:02 <a href="http://www.blogjava.net/kissyan4916/articles/339676.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）安卓必读：Android系统架构基本模式解析(2010-12-01 :54)</title><link>http://www.blogjava.net/kissyan4916/articles/339574.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Thu, 02 Dec 2010 01:59:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/339574.html</guid><description><![CDATA[如今，大家面对市场中种类繁多的手机必然挑的眼花缭乱。不过，在智能手机占据主要地位的今天，挑选手机的主要因素就是挑选一款性能高的手机操作系
统，Android就是其中的一个必然选择。Android系统架构和其操作系统一样，采用了分层的架构。Android分为四个层，从高层到低层分别是
应用程序层、应用程序框架层、系统运行库层和linux核心层。<br />
<br />
<strong>Android系统架构之应用程序</strong><br />
<br />
Android会同一系列核心应用程序包一起发布，该应用程序包包括email客户端，SMS短消息程序，日历，地图，浏览器，联系人管理程序等。所有的应用程序都是使用JAVA语言编写的。<br />
<br />
<strong>Android系统架构之应用程序框架</strong><br />
<br />
开发人员也可以完全访问核心应用程序所使用的API框架。该应用程序的架构设计简化了组件的重用;任何一个应用程序都可以发布它的功能块并且任何其它的
应用程序都可以使用其所发布的功能块(不过得遵循框架的安全性限制)。同样，该应用程序重用机制也使用户可以方便的替换程序组件。<br />
<br />
隐藏在每个应用后面的是一系列的服务和系统, 其中包括;<br />
<br />
* 丰富而又可扩展的视图(Views)，可以用来构建应用程序， 它包括列表(lists)，网格(grids)，文本框(text boxes)，按钮(buttons)， 甚至可嵌入的web浏览器。<br />
<br />
* 内容提供器(Content Providers)使得应用程序可以访问另一个应用程序的数据(如联系人数据库)， 或者共享它们自己的数据<br />
<br />
* 资源管理器(Resource Manager)提供 非代码资源的访问，如本地字符串，图形，和布局文件( layout files )。<br />
<br />
* 通知管理器 (Notification Manager) 使得应用程序可以在状态栏中显示自定义的提示信息。<br />
<br />
* 活动管理器( Activity Manager) 用来管理应用程序生命周期并提供常用的导航回退功能。<br />
<br />
有关更多的细节和怎样从头写一个应用程序，请参考 如何编写一个 Android 应用程序.<br />
<br />
<strong>Android系统架构之系统运行库</strong><br />
<br />
1)程序库<br />
<br />
Android 包含一些C/C++库，这些库能被Android系统中不同的组件使用。它们通过 Android 应用程序框架为开发者提供服务。以下是一些核心库：<br />
<br />
* 系统 C 库 - 一个从 BSD 继承来的标准 C 系统函数库( libc )， 它是专门为基于 embedded linux 的设备定制的。<br />
<br />
* 媒体库 - 基于 PacketVideo OpenCORE;该库支持多种常用的音频、视频格式回放和录制，同时支持静态图像文件。编码格式包括MPEG4, H.264, MP3, AAC, AMR, JPG, PNG 。<br />
<br />
* Surface Manager - 对显示子系统的管理，并且为多个应用程序提 供了2D和3D图层的无缝融合。<br />
<br />
* LibWebCore - 一个最新的web浏览器引擎用，支持Android浏览器和一个可嵌入的web视图。<br />
<br />
* SGL - 底层的2D图形引擎<br />
<br />
* 3D libraries - 基于OpenGL ES 1.0 APIs实现;该库可以使用硬件 3D加速(如果可用)或者使用高度优化的3D软加速。<br />
<br />
* FreeType -位图(bitmap)和矢量(vector)字体显示。<br />
<br />
* SQLite - 一个对于所有应用程序可用，功能强劲的轻型关系型数据库引擎。<br />
<br />
2)Android 运行库<br />
<br />
Android 包括了一个核心库，该核心库提供了JAVA编程语言核心库的大多数功能。<br />
<br />
每一个Android应用程序都在它自己的进程中运行，都拥有一个独立的Dalvik虚拟机实例。Dalvik被设计成一个设备可以同时高效地运行多个
虚拟系统。
Dalvik虚拟机执行(.dex)的Dalvik可执行文件，该格式文件针对小内存使用做了优化。同时虚拟机是基于寄存器的，所有的类都经由JAVA编
译器编译，然后通过SDK中 的 &#8220;dx&#8221; 工具转化成.dex格式由虚拟机执行。<br />
<br />
Dalvik虚拟机依赖于linux内核的一些功能，比如线程机制和底层内存管理机制。<br />
<br />
<strong>Android系统架构之Linux 内核</strong><br />
<br />
Android 的核心系统服务依赖于 Linux 2.6 内核，如安全性，内存管理，进程管理， 网络协议栈和驱动模型。 Linux 内核也同时作为硬件和软件栈之间的抽象层。<img src ="http://www.blogjava.net/kissyan4916/aggbug/339574.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-12-02 09:59 <a href="http://www.blogjava.net/kissyan4916/articles/339574.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（转）应用程序签名</title><link>http://www.blogjava.net/kissyan4916/articles/338807.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Tue, 23 Nov 2010 07:34:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/338807.html</guid><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 概述Android系统要求，所有的程序经过数字签名后才能安装。Android系统使用这个证书来识别应用程序的作者，并且建立程序间的信任关系。证书不是用于用户控制哪些程序可以安装。证书不需要授权中心来签名：Android应用程序上使用自己签名的证书是完全允许且普遍的。理解Android应用程序签名有以下几个重要点：&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp...&nbsp;&nbsp;<a href='http://www.blogjava.net/kissyan4916/articles/338807.html'>阅读全文</a><img src ="http://www.blogjava.net/kissyan4916/aggbug/338807.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-11-23 15:34 <a href="http://www.blogjava.net/kissyan4916/articles/338807.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(转)在Android模拟器中使用google maps的基本配置 </title><link>http://www.blogjava.net/kissyan4916/articles/338760.html</link><dc:creator>金色闪电</dc:creator><author>金色闪电</author><pubDate>Tue, 23 Nov 2010 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/kissyan4916/articles/338760.html</guid><description><![CDATA[<p>前言：</p>
<p>今天翻了一个上午的网络，在android 模拟器下配置google maps遇到了问题，查阅了一堆资料，多数讲解的不是很清晰，呵呵，经过多次试验终于OK了，现把每一步详细列出来，提供给像我这样的初学者。大家共同进步</p>
<p><br />
1)首先你要确定你安装的JDK位置，Windows-&gt;Preferences-&gt;Java-&gt;Installed JREs,你可以看到是Jre的location,再在dos cmd模式下查看你当前系统的path是否已经包含了。如果没有包含添加到当前环境参数中。因为我们要用到的keytool命令在这个目录下呀。<br />
2)接下来就要找到你不前AVD的debug.keystore的位置，windows-&gt;perferences-&gt;android-&gt;build,<br />
default debug keystore文本框中，列出C:\Documents and Settings\XXXXuser\.android\debug.keystore,这就是默认的debug.keystore,你可以先把这个文件改一下名。我们需要创建一个新的debug.keystore<br />
3)紧接着我们来创建一个新的debug.keystore,在cmd下，进入C:\Documents and Settings\XXXXuser\.android目录<br />
执行命令如下：<br />
<strong>keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -keyalg RSA -validity 10000<br />
</strong>输入密码，用户等信息确认后生成一个debug.keystore<br />
4)好了，接下来我们就需要获取MD5,去google申请一个apikey,很简单<br />
在当前目录下执行：<br />
<strong>keytool -list -alias androiddebugkey -keystore debug.keystore<br />
</strong>根据提示输入你在第三步所设的密码，ok,就会得到下面信息，<br />
Certificate fingerprint (MD5): <span style="color: red">FC:ED:DE:BS:16:1A:E8:05:F0:44:AD:4E:45:42:4B:D4</span><br />
这就是我们申请apikey时需要的FC:ED:DE:BS:16:1A:E8:05:F0:44:AD:4E:45:42:4B:D4<br />
通过浏览器访问<a href="http://code.google.com/android/maps-api-signup.html" target="_blank">http://code.google.com/android/maps-api-signup.html</a><br />
在My certificate's MD5 fingerprint文本框中输入您刚刚获取到的MD5码<br />
点击Generate API Key，<br />
Thank you for signing up for an Android Maps API key!<br />
Your key is:<br />
<span style="color: red">0yRkOg8325bNSbeuYXZMsj-CMG2rXXXqFBoa11A</span><br />
这就是apikey了，记得保存下呀</p>
<p>5)新建一个android项目<br />
修改main.xml<br />
&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;LinearLayout xmlns:android="<a href="http://schemas.android.com/apk/res/android" target="_blank">http://schemas.android.com/apk/res/android</a>"<br />
&nbsp;&nbsp;&nbsp; android:orientation="vertical"<br />
&nbsp;&nbsp;&nbsp; android:layout_width="fill_parent"<br />
&nbsp;&nbsp;&nbsp; android:layout_height="fill_parent"<br />
&nbsp;&nbsp;&nbsp; &gt;<br />
&lt;view class = "com.google.android.maps.MapView"&nbsp; <br />
&nbsp;android:id = "@+id/my_map"<br />
&nbsp;android:enabled = "true"<br />
<span style="color: red">&nbsp;android:apiKey="0yRkOg8325bNSbeuYXZMsj-CMG2rXXXqFBoa11A" </span><br />
&nbsp;&nbsp;&nbsp; android:layout_width="fill_parent" <br />
&nbsp;&nbsp;&nbsp; android:layout_height="wrap_content" <br />
&nbsp;&nbsp;&nbsp; /&gt;<br />
&lt;/LinearLayout&gt;<br />
在layout中定义mapview时需要加入apikey, 如：android:apiKey="0yRkOg8325bNSbeuYXZMsj-CMG2rXXXqFBoa11A" <br />
6)修改androidmanifest.xml<br />
&lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&lt;manifest xmlns:android="<a href="http://schemas.android.com/apk/res/android" target="_blank">http://schemas.android.com/apk/res/android</a>"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; package="com.testmap"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:versionCode="1"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:versionName="1.0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;application android:icon="@drawable/icon" android:label="@string/app_name"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: red"> &lt;uses-library&nbsp; android:name="com.google.android.maps" /&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".testmap"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:label="@string/app_name"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;intent-filter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action android:name="android.intent.action.MAIN" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.LAUNCHER" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/intent-filter&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/activity&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;/application&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;uses-sdk android:minSdkVersion="5" /&gt;<br />
<span style="color: red">&lt;uses-permission android:name="android.permission.INTERNET"&gt;&lt;/uses-permission&gt;</span><br />
&lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"&gt;&lt;/uses-permission&gt;<br />
&lt;uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"&gt;&lt;/uses-permission&gt;<br />
&lt;/manifest&gt;</p>
<p>我们需要加入用户库引用&lt;uses-library&nbsp; android:name="com.google.android.maps" /&gt; <br />
当然了还要加入权限的定义<br />
&lt;uses-permission android:name="android.permission.INTERNET"&gt;&lt;/uses-permission&gt;<br />
这两步必不可少</p>
<p>7）最后就是主class了</p>
<div class="cnblogs_code">
<div><!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />--><span style="color: #000000"><br />
<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;com.google.android.maps.GeoPoint;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;com.google.android.maps.MapActivity;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;com.google.android.maps.MapController;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;com.google.android.maps.MapView;<br />
</span><span style="color: #0000ff">import</span><span style="color: #000000">&nbsp;android.os.Bundle;<br />
<br />
<br />
</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;testmap&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;MapActivity&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">/**</span><span style="color: #008000">&nbsp;Called&nbsp;when&nbsp;the&nbsp;activity&nbsp;is&nbsp;first&nbsp;created.&nbsp;</span><span style="color: #008000">*/</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;onCreate(Bundle&nbsp;savedInstanceState)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">super</span><span style="color: #000000">.onCreate(savedInstanceState);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setContentView(R.layout.main);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">get&nbsp;map&nbsp;view</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MapView&nbsp;mv&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(MapView)&nbsp;findViewById(R.id.my_map);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MapController&nbsp;controller&nbsp;&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(MapController)mv.getController();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GeoPoint&nbsp;p&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;GeoPoint((</span><span style="color: #0000ff">int</span><span style="color: #000000">)&nbsp;(</span><span style="color: #000000">24.7</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1000000</span><span style="color: #000000">),(</span><span style="color: #0000ff">int</span><span style="color: #000000">)(</span><span style="color: #000000">-</span><span style="color: #000000">238.8</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1000000</span><span style="color: #000000">));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controller.animateTo(p);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;controller.setZoom(</span><span style="color: #000000">9</span><span style="color: #000000">);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">boolean</span><span style="color: #000000">&nbsp;isRouteDisplayed()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">return</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
<br />
</span></div>
</div><img src ="http://www.blogjava.net/kissyan4916/aggbug/338760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kissyan4916/" target="_blank">金色闪电</a> 2010-11-23 10:27 <a href="http://www.blogjava.net/kissyan4916/articles/338760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>