2015-08-10 13:10:05 chuyouyinghe 阅读数 1483
  • Android移植基础

    Android视频课程,该课程可以让学员了解Android系统架构、学习如何下载Android源码、编译及开发Android、学习如何追踪Android源码、了解Linux内核启动流程、了解Android启动流程、学习如何移植外部函式库至Android源码中。

    26242 人正在学习 去看看 钟文昌
最近常有人问,刚刚学Android什么样的书比较好,比较适合我呢?于是乎便有了这个文章,从基础入门到进阶高手,这些都是我感觉很不错的,重要的是免费下载。不过还是建议大家买纸质版,这样看起来比较爽。


入门书籍:


1Java编程思想第四版
从本书获得的各项大奖以及来自世界各地的读者评论中,不难看出这是一本经典之作。本书的作者拥有多年教学经验,对CC++以及Java语言都有独到、深入的见解,以通俗易懂及小而直接的示例解释了一个个晦涩抽象的概念。本书共22章,包括操作符、控制执行流程、访问权限控制、复用类、多态、接口、通过异常处理错误、字符串、泛型、数组、容器深入研究、Java I/O系统、枚举类型、并发以及图形化用户界面等内容。这些丰富的内容,包含了Java语言基础语法以及高级特性,适合各个层次的Java程序员阅读,同时也是高等院校讲授面向对象程序设计语言以及Java语言的绝佳教材和参考书。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=91263&extra=page%3D1%26filter%3Dsortid%26sortid%3D8


2Head First Java
Head First Java(中文版)(2)是本完整的面向对象(object-orientedOO)程序设计和Java的学习指导。此书是根据学习理论所设计的,让你可以从学习程序语言的基础开始一直到包括线程、网络与分布式程序等项目。最重要的,你会学会如何像个面向对象开发者一样去思考。
而且不只是读死书,你还会玩游戏、拼图、解谜题以及以意想不到的方式与Java交互。在这些活动中,你会写出一堆真正的Java程序,包括了一个船舰炮战游戏和一个网络聊天程序。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=244162



3、疯狂Android讲义
计算机便携化是未来的发展趋势,而Android作为最受欢迎的手机、平板电脑操作之一,其发展的上升势头是势不可当的。而Android应用选择了Java作为其开发语言,对于Java来说也是一次极好的机会。
本书并不局限于介绍Android编程的各种理论知识,而是从“项目驱动”的角度来讲授理论,全书一共包括近百个实例,这些示范性的实例既可帮读者更好地理解各知识点在实际开发中的应用,也可供读者在实际开发时作为参考、拿来就用。本书最后还提供了两个实用的案例:疯狂连连看和电子拍卖系统Android客户端,具有极高的参考价值。本书提供了配套的答疑网站,如果读者在阅读本书时遇到了技术问题,可以登录疯狂Java联盟发帖,笔者将会及时予以解答。
本书适合于有一定Java编程基础的读者。如果读者已熟练掌握Java编程语法并具有一定图形界面编程经验,阅读本书将十分合适。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=178310&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



4、第一行代码——Android
《第一行代码——Android》是Android初学者的最佳入门书。全书由浅入深、系统全面地讲解了Android软件开发的方方面面。
第1章带领你搭建Android开发环境,完成你的第一个Android程序。
第2章至第13章完整地讲解了Android开发中的各种基本知识和关键技术,包括四大组件、UI、碎片、广播机制、数据存储、服务、多媒体、网络、定位服务、传感器,以及分布式版本控制系统Git的使用等等。 在部分章节会穿插相关技术的高级使用技巧。
第14章和第15章则将带领你编写一个完整的项目,教会你如何打包、上架、嵌入广告并获得盈利。
《第一行代码——Android》内容通俗易懂,既适合初学者循序渐进地阅读,也可作为一本参考手册,随时查阅。

下载地址:



5Google Android开发入门与实战
本书内容上覆盖了用Android开发的大部分场景,从Android基础介绍、环境搭建、SDK介绍、Market使用,到应用剖析、组件介绍、实例演示等方面。从技术实现上,讲解了5个Android平台下的完整综合实例及源代码分析,分别是RSS阅读器、基于Google Map的个人GPS、豆瓣网(Web 2.0)客户端、在线音乐播放器、手机信息助手。
本书注重对实际动手能力的指导,在遵循技术研发知识体系的严密性同时,在容易产生错误、不易理解的环节配以了详实的开发情景截图,并将重要的知识点和经验技巧以“小实验”、“小知识”的活泼形式呈现给读者。在程序实例的讲解方面,将实例安插在Android开发的精髓知识章节,这为初学者学习与实践结合提供了很好的指导。.
本书配套有300多分钟的全程开发视频光盘,指导读者快速、无障碍地学通Android实战开发技术。..
本书适合具备一定软件开发经验,想快速进入Android开发领域的程序员;具备一些手机开发经验的开发者和Android开发爱好者学习用书;也适合作为相关培训学校的Android培训教材。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=242538&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



6Android-Training-Course-in-Chinese官方培训课程中文版
Google Android团队在2012年开设了培训课程,从开始的10几篇文章,不断的增加与更新,直到现在2014年中,已经有近百个课程,200篇左右的文章。这是一份学习Android应用开发的绝佳资料。

现在已经被翻译为中文版
https://github.com/kesenhoo/android-training-course-in-chinese

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=240881&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



714天学会安卓开发
快速的Android开发实战教程,14天学会安卓开发-完整版 pdf教程电子书下载,第1天:Android架构与环境搭建;第2天:Android程序设计基础;第3天:UI事件处理与布局管理;第4天:基础UI控件介绍及使用方法;第5天:高级UI控件使用;第6天:Android Service;第7天:SharedPreferences与文件;第8天:Sqlite数据库技术教程及应用;第9天:Android网络与通信;第10天:ContentProvider与BroadcastReceiver;第11天:Android图形技术;第12天:Android动画技术;第13天:Android多媒体开发

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=241178&extra=page%3D2%26filter%3Dsortid%26orderby%3Dlastpost%26sortid%3D8


进阶书籍:



1PhoneGap实战

PhoneGap实战由来自腾讯的资深专家团队撰写,Adobe中国区专家和PhoneGap中国社区联袂推荐。本书内容全面、注重实战、启发性强,对PhoneGap的所有功能、特性、使用方法和开发技巧进行了全面而透彻的讲解,是系统学习PhoneGap的权威参考书。全书一共10章:第1章主要介绍PhoneGap的用途、与其他同类框架的比较,以及Web开发的入门知识;第2章详细讲解PhoneGap在各个移动平台上的安装与配置;第3章通过一个汇率计算器实例讲解PhoneGap应用开发的完整流程和相关技术细节;第4章详细讲解PhoneGap的API;第5章和第6章是两个综合性的案例(指南针、万圣节更衣室),它们都遵循构想、设计、开发、调试、发布五大流程,从实战出发,由浅入深,逐步推进;第7章介绍PhoneGap应用在各个平台上的发布流程与方法;第8章从不同的平台、视觉风格、交互设计、移动应用选型等角度分享了移动应用产品设计的一些技巧和最佳实践;第9章讲解PhoneGap与jQueryMobile的结合使用;第10章介绍PhoneGap插件的使用。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=244205&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



2
深入理解Android 1
《深入理解Android(卷1)》是一本以情景方式对Android的源代码进行深入分析的书。内容广泛,以对Framework层的分析为主,兼顾Native层和Application层;分析深入,每一部分源代码的分析都力求透彻;针对性强,注重实际应用开发需求,书中所涵盖的知识点都是Android应用开发者和系统开发者需要重点掌握的。
下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=242171&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



3Android多媒体开发高级编程
Android多媒体开发高级编程——为智能手机和平板电脑开发图形、音乐、视频和富媒体应用》使用清晰、直观的示例介绍了Android SDK中丰富的多媒体功能,有助于您开发能够创建、播放和共享多媒体的优秀Android应用程序。许多Android设备本身就是照相机、相册、摄像机、电影播放器、音乐播放器以及录音机——为何不在应用程序中使用所有这些及更多的功能?这些令人激动的功能将使您的应用程序熠熠生辉,实现更多的用途。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=241182&extra=page%3D1%26filter%3Dsortid%26sortid%3D8


高手必读书籍:



1Android内核剖析
Android内核剖析内容分别从基础、内核、系统、编译以及硬件驱动几个方面对Android内核相关知识进行深入剖析,详细分析了Android内核的内部机制,包括窗口管理系统、Activity管理系统、输入法框架、编译系统等,为Android内核定制以及高级应用程序开发提供技术参考。
Android内核剖析适合于所有Android相关的工程师以及产品经理。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=244159&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



2、
编程珠玑第二版

本书是计算机科学方面的经典名著。书的内容围绕程序设计人员面对的一系列实际问题展开。作者Jon Bentley 以其独有的洞察力和创造力,引导读者理解这些问题并学会解决方法,而这些正是程序员实际编程生涯中至关重要的。本书的特色是通过一些精心设计的有趣而又颇具指导意义的程序,对实用程序设计技巧及基本设计原则进行了透彻而睿智的描述,为复杂的编程问题提供了清晰而完备的解决思路。本书对各个层次的程序员都具有很高的阅读价值。
下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=242264&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



3、调试九法—软硬件错误的排查之道
《调试九法》是2010年人民邮电出版社出版的图书,作者是DavidJ.Agans。
硬件缺陷和软件错误是“技术侦探”的劲敌,它们负隅顽抗,见缝插针。本书提出的九条简单实用的规则,适用于任何软件应用程序和硬件系统,可以帮助软硬件调试工程师检测任何bug,不管它们有多么狡猾和隐秘。
作者使用真实示例展示了如何应用简单有效的通用策略来排查各种各样的问题,例如芯片过热、由蛋酒引起的电路短路、触摸屏失真,等等。本书给出了真正能够隔离关键因素、运行测试序列和查找失败原因的技术。
无论你的系统或程序发生了设计错误、构建错误还是使用错误,本书都可以帮助你用正确的方法来思考,使bug自动暴露,进而一网打尽,斩草除根。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=242164&extra=page%3D2%26filter%3Dsortid%26orderby%3Dlastpost%26sortid%3D8



自我培养类型:



1、程序员的思维修炼:开发认知潜能的九堂课
运用一门程序设计语言编程对大多数普通程序员来说是“小菜一碟”,那么如何更上层楼成为一名专家级的软件开发者呢?本书给出了答案——优秀的学习能力和思考能力。作者从软件开发领域的角度,阐述了每一名程序员提升“内力”所需要的各种软性知识:从新手到专家的5个层次、人类大脑的运行机制、直觉和理性的利与弊、学习方法和实践经验的重要性、控制注意力的技巧,等等,可谓是一本程序员“素质教育”的微型百科全书。我非常支持一个白话版的“素质”定义:除了书本知识、硬性记忆以外的东西,扪心自问,包括我自己在内的大多数程序员除了固化的编程知识以外,又有多少“素质”拿得出手呢?IT领域知识更新换代之快需要我们不停地往前奔跑,当我们痛苦地追逐时尚的新鲜玩意时,更需放慢脚步,冷静地修炼自己的“内功”,以不变应万变,才能立于不败之地。如果你想改变现状,本书可以作为一个良好的起点。作者对各种软性技能都做了深入研究,并结合自己的经验总结成你可以借鉴的知识点,让你无需阅读各个领域(认知科学、神经学、行为理论)的专著,就能够汲取适合自己的精华。

下载地址:
http://www.apkbus.com/forum.php?mod=viewthread&tid=241871&extra=page%3D1%26filter%3Dsortid%26sortid%3D8



转自:http://www.apkbus.com/forum.php?mod=viewthread&tid=244362&extra=

2015-03-09 16:46:52 dnbird1987 阅读数 150
  • Android移植基础

    Android视频课程,该课程可以让学员了解Android系统架构、学习如何下载Android源码、编译及开发Android、学习如何追踪Android源码、了解Linux内核启动流程、了解Android启动流程、学习如何移植外部函式库至Android源码中。

    26242 人正在学习 去看看 钟文昌

Android 3D游戏开发技术宝典(PDF教程下载)

1

图书描述
《Android 3D游戏开发技术宝典:OpenGL ES 2.0》内容简介:随着智能手机移动嵌入式平台硬件性能的不断提升,3D游戏应用也逐渐普及开来。《Android 3D游戏开发技术宝典:OpenGL ES 2.0》结合作者多年从事3D游戏应用开发的宝贵经验,全面介绍了与Android平台相关的必知必会的基础知识及大型完整3D案例,讲解上由浅入深,循序渐进,起点低、终点高,既适合初学者学习,也适合有一定基础的读者进一步提升之用。另外,由于OpenGL ES2.0的着色语言通用于各种移动嵌入式平台,因此,《Android 3D游戏开发技术宝典:OpenGL ES 2.0》中与着色器开发相关的60%左右的内容还可供iPhone、Windows Mobile、MeeGoo等平台的开发人员参考。全书共22章,其中第1章与第2章为Android平台相关的一些基础知识;第3章~第10章介绍了基于OpenGL ES2.0进行3D应用开发的一些必知必会的基本知识;第11章~第15章介绍了一些高级特效的实现方法;第16章~第17章介绍了3D游戏开发中相关的一些物理、碰撞检测知识以及常用的3D物理引擎JBullet:第19章介绍了3种人机交互的高级技术;第20章~第22章给出了3个完整的大型3D游戏案例,总代码量接近6万行。同时为了便于读者的学习,《Android 3D游戏开发技术宝典:OpenGL ES 2.0》附赠的光盘中包含了书中所有案例的完整源代码,同时给出了最后3个完整大型3D游戏案例的讲解视频,最大限度地帮助读者快速掌握相应的开发技术。

编辑推荐
《Android 3D游戏开发技术宝典:OpenGL ES 2.0》适合Android程序员、游戏开发者及Android爱好者学习,也可以作为相关培训学校和大专院校相关专业的教学用书。
《Android 3D游戏开发技术宝典:OpenGL ES 2.0》组织上本着“起点低,终点高”的原则,内容覆盖了从学习OpenGL ES 2.0必知必会的基础知识到基于OpenGL ES 2.0实现高级特效,最后还给出了3个完整的大型3D游戏案例。这3个案例均是笔者带领学员参加谷歌(Google)2011第二届Android应用开发中国大学生挑战赛的获奖作品,第22章的夜鹰行动更是获全国总决赛前5名大奖的作品。
《Android 3D游戏开发技术宝典:OpenGL ES 2.0》中配合每个需要讲解的知识点都给出了丰富的插图与完整的案例,使得初学者易于上手,有一定基础的读者便于深入。书中所有的案例均是根据笔者多年的开发心得进行设计的,结构清晰明朗,便于读者进行学习。同时书中还给出了很多笔者多年来积累的编程技巧与心得,具有很高的参考价值。

作者简介
吴亚峰,毕业于北京邮电大学,后留学澳大利亚卧龙岗大学取得硕士学位。1998年开始从事Java应用的开发,有10多年的.1ava开发与培训经验。主要的研究方向为OpenGLES、手机游戏、Java EE以及搜索引擎。同时为手机游戏、Java EE独立软件开发工程师,并兼任百纳科技Java培训中心首席培训师。近十年来为数十家著名企业培养了上千名高级软件开发人员,曾编写过《JavaSE 6.0编程指南》、《菜鸟成长之路——Java程序员职场全攻略》、《Android 2.0游戏开发实战宝典》、《Android核心技术与实例详解》、《Android应用案例开发大全》、《Android游戏开发大全》、《Android应用开发完全自学手册——核心技术、传感器、2D/3D、多媒体与典型案例》等多本畅销技术书籍。2008年年初开始关注Android平台下的应用开发,并开发出一系列优秀的Android应用程序与游戏。
目录

第1章 新一代的王者——Android概览
1.1 智能手机市场现状
1.1.1 五大智能手机操作系统
1.1.2 智能手机市场的新星
1.2 Android 平台的特点及未来的趋势
1.2.1 全新理念带来的体验风暴
1.2.2 中国手机市场的主导性作用
1.2.3 手机3D游戏和应用增长迅速
1.3 如何搭建Android开发环境
1.3.1 SDK的安装及环境配置
1.3.2 Eclipse集成开发环境的搭建
1.3.3 创建并启动模拟器
1.4 Hello Android应用程序的开发
1.4.1 第一个Android应用程序
1.4.2 Android应用程序的项目结构
1.4.3 Android应用程序的调试
1.4.4 实际设备的联机调试
1.5 Android 应用程序运行的机制
1.5.1应用程序的系统架构
1.5.2 应用程序框架
1.5.3 Android运行时
1.5.4 系统库
1.5.5底层Linux内核
1.6 本章小结
第2章 游戏开发相关Android基础知识
2.1 游戏中的音效
2.1.1 游戏中的即时音效
2.1.2 即时音效的一个案例
2.1.3 背景音乐播放技术
2.1.4 简易音乐播放器的实现
2.2 简单数据的存储——Preferences
2.2.1 Preferences简介33
2.2.2 Preferences实现访问时间的记录
2.3 手机自带数据库——SOLite
2.3.1 初识SOLite
2.3.2 SQLite数据库的基本操作
2.3.3 SQLite数据库的简单案例
2.3.4 使用ContentProvider组件共享数据
2.3.5 使用ContentResolver获取分享数据
2.4.文件I/O
2.4.1 访问SD卡中的文件
2.4.2 访问手机中的文件夹
2.4.3 读取assets文件夹下的内容
2.5 2D动画的开发
2.5.1 SurflaceView用法简介
2.5.2 使用SurfaceView实现2D动画
2.6 Socket网络通信
2.6.1 Socket开发基本知识
2.6.2 服务器端
2.6.3 客户端
2.7蓝牙通信
2.7.1 蓝牙通信的基本知识
2.7.2 聊天案例概览
2.7.3 聊天案例的开发过程
2.8 本章小结
第3章 初识OpenGL ES 2.0
3.1 OpenGL ES 2.0概览
3.1.1 OpenGL ES 2.0简介
3.1.2 初识 OpenGL ES 2.0 应用程序
3.2 着色器与渲染管线
3.2.1 OpenGL ES 1.x的渲染管线
3.2.2 OpenGL ES 2.0的渲染管线
3.2.3 OpenGL ES中立体物体的构建
3.3 主流Android手机GPU大PK
3.3.1 手机GPU大家族对比
3.3.2 主流GPU的性能参数比较
3.4 本章小结
第4章 着色语言Shading Language
4.1 着色语言概述
4.2 着色语言基础
4.2.1 数据类型概述
4.2.2 数据类型的基本使用
4.2.3 运算符
4.2.4 类型转换
4.2.5 限定符
4.2.6 流程控制
4.2.7 函数的声明与使用
4.2.8 片元着色器中浮点变量精度的指定
4.2.9 程序的基本结构
4.3 特殊的内建变量
4.3.1 顶点着色器中的内建变量
4.3.2 片元着色器中的内建变量
4.4 着色语言的内置函数
4.4.1 角度转换与三角函数
4.4.2 指数函数
4.4.3 常见函数
4.4.4 几何函数
4.4.5 矩阵函数
4.4.6 向量关系函数
4.4.7 纹理采样函数
4.4.8 微分函数
4.5 本章小结
第5章 投影及各种变换
5.1 摄像机的设置
5.2 两种投影方式
5.2.1 正交投影
5.2.2 透视投影
5.3 各种变换
5.3.1 基本变换的相关数学知识
5.3.2 平移变换
5.3.3 旋转变换
5.3.4 缩放变换
5.3.5 基本变换的实质
5.4 绘制方式
5.4.1 各种绘制方式概览
5.4.2 点与线段绘制方式
5.4.3 三角形条带与扇面绘制方式
5.4.4.顶点法与索引法
5.5 设置合理的视角
5.6 卷绕和背面剪裁
5.6.1 基本知识
5.6.2 一个简单的案例
5.7 本章小结
……
第6章 光照
第7章 纹理映射
第8章 3D基本形状的构建
第9章 3D模型加载
第10章 混合与雾
第11章 常用3D开发技巧
第12章 几种剪裁与测试
第13章 顶点着色器的妙用
第14章 片元着色器的妙用
第15章 真实光学环境的模拟
第16章 游戏开发中的物理学
第17章 游戏的心脏——物理引擎
第18章 传感器应用的开发
第19章 游戏开发小贴士
第20章 BN赛艇
第21章 火力篮球
第22章 夜鹰行动

百度网盘:http://pan.baidu.com/s/1c0Iqs3e

 

 

 

android从入门到精通(电子书下载)-百度网盘

1
内容简介:
    本书注重实际动手能力的培养,在遵循技术研发知识体系的严密性的同时,在容易产生错误、不易理解的环节配上翔实的开发实例呈现给读者。每一个实例都经过精心挑选,解释详尽,使读者在实例学习中掌握Android编程思想和编程技巧。本书配有源代码,读者可快速、无障碍地学习Android实战开发技术。

目录

第1章 初识Android
  1.1 什么是Android
  1.1.1 移动信息设备分类
  1.1.2 Open Handset Alliance和Android
  1.2 Android简介
  1.2.1 Andriod的历史
  1.2.2 Andriod的未来
  1.2.3 Andriod平台的技术架构
  1.3 Android应用程序构成
  1.3.1 活动(Activity)
  1.3.2 意图(Intent)
  1.3.3 服务(Service)
  1.3.4 内容提供器(ContentProvider)
  1.4 Android网上资源
第2章 搭建Android开发环境
  2.1 Android开发环境要求
  2.2 JDK的安装和配置
  2.2.1 安装JDK
  2.2.2 配置JDK
  2.3 Android SDK的下载和安装
  2.3.1 下载Android SDK
  2.3.2 安装Android SDK
  2.3.3 创建Android虚拟设备
  2.4 Eclipse的下载和安装
  2.4.1 下载和安装Eclipse
  2.4.2 安装和配置Eclipse中Android插件
  2.5 使用Eclipse开发Android应用程序
  2.5.1 使用Eclipse创建Android项目
  2.5.2 Eclipse中Android项目架构
  2.5.3 Eclipse中Android项目的调试和运行
第3章 Android中的Activity
  3.1 Activity的作用
  3.2 单Activity的Android应用
  3.2.1 Activity的生命周期
  3.2.2 Activity类的结构
  3.3 Activity的两种界面设计方式
  3.3.1 基于XML的界面设计
  3.3.2 基于代码的界面设计
  3.4 应用实例:在界面中显示图片
第4章 Android人机界面和常用组件
  4.1 用户人机界面元素分类
  4.1.1 视图组件(View)
  4.1.2 视图容器组件(ViewGroup)
  4.1.3 布局组件(Layout)
  4.1.4 布局参数(LayoutParams)
  4.2 常用Widget组件
  4.2.1 文本框视图(TextView)
  4.2.2 按钮(Button)
  4.2.3 图片按钮(ImageButton)
  4.2.4 编辑框(EditText)
  4.2.5 多项选择(CheckBox)
  4.2.6 单项选择(RadioGroup)
  4.2.7 下拉列表(Spinner)
  4.2.8 自动完成文本框视图(AutoCompleteTextView)
  4.2.9 日期选择器(DatePicker)
  4.2.10 时间选择器(TimePicker)
  4.2.11 数字时钟(DigitalClock)
  4.2.12 表状时钟(AnalogClock)
  4.2.13 进度条(ProgressBar)
  4.2.14 拖动条(SeekBar)
  4.2.15 评分条(RatingBar)
第5章 Android中的视图组件
  5.1 视图组件
  5.1.1 图片视图(ImageView)
  5.1.2 滚动视图(ScrollView)
  5.1.3 网格视图(GridView)
  5.1.4 列表视图(ListView)
  5.1.5 切换图片(ImageSwitcher和Gallery)
  5.1.6 标签切换(Tab)
  5.2 通用XML属性
第6章 Android菜单和布局设计
  6.1 菜单(Menu)
  6.1.1 上下文菜单(ContextMenu)
  6.1.2 选项菜单(OptionsMenu)
  6.1.3 基于XML的菜单结构
  6.2 界面布局设计
  6.2.1 基于XML的布局设计
  6.2.2 线性布局(LinearLayout)
  6.2.3 相对布局(RelativeLayout)
  6.2.4 表格布局(TableLayout)
  6.2.5 绝对布局(AbsoluteLayout)
  6.3 界面中的字体
  6.3.1 设置系统字体
  6.3.2 引用用户自定义字体
  6.4 应用实例详解:制作手机桌面
  6.4.1 实例分析
  6.4.2 实例实现
第7章 Android中的核心Intent
  7.1 Intent的作用
  7.1.1 多Activity的Android应用
  7.1.2 Activity之间的消息传递
  7.2 Intent的分类
  7.2.1 Action Intent
  7.2.2 Broadcast Intent
  7.3 解析Intent的实现
  7.3.1 Intent Receiver
  7.3.2 Intent Filter
  7.4 设置Activity许可
  7.5 应用实例详解:电话拨号程序
  7.5.1 实例分析
  7.5.2 实例实现
第8章 Android中的后台服务Service
  8.1 Service的作用
  8.2 Service的实现
  8.2.1 创建Service
  8.2.2 启动Service
  8.3 Toast和Notification应用
  8.3.1 使用Notification通知
  用户服务启动
  8.3.2 使用Toast显示通知信息
  8.4 应用实例详解:播放背景音乐
  8.4.1 实例分析
  8.4.2 实例实现
第9章 Android中的数据存储
  9.1 使用Preferences存储数据
  9.1.1 访问Preferences的API
  9.1.2 使用XML存储Preferences数据
  9.2 使用文件存储数据
  9.2.1 访问应用中的文件数据
  9.2.2 访问设备中独立的文件数据
  9.3 使用SQLite数据库存储数据
  9.3.1 SQLite数据库简介
  9.3.2 SQLite数据库操作
  9.3.3 使用SQLiteDatabase对象操作数据库
  9.3.4 Cursor的使用
  9.4 使用ContentProvider
  9.4.1 定义ContentProvider
  9.4.2 使用ContentProvider进行CRUD操作
  9.5 应用实例详解:创建音乐
  播放列表
  9.5.1 实例分析
  9.5.2 实例实现
第10章 Android的网络通信
  10.1 访问Internet
  10.1.1 使用WebKit组件访问Internet
  10.1.2 使用Apache HttpComponents访问Internet
  10.2 Socket通信
  10.3 应用实例详解:手机 短信程序
  10.3.1 实例分析
  10.3.2 实例实现
第11章 Android的GPS应用开发
  11.1 GPS在手机中的应用
  11.2 Android Location-Based API简介
  11.3 Android模拟器支持的GPS定位文件
  11.3.1 KML
  11.3.2 NMEA
  11.4 应用实例详解:确定当前 位置的GPS程序
  11.4.1 实例分析
  11.4.2 实例实现
  11.5 基于Google Map的应用
  11.5.1 使用MapView显示地图
  11.5.2 使用MapController控制地图缩放
  11.6 应用实例详解:普通地图和卫星地图切换
  11.6.1 实例分析
  11.6.2 实例实现
第12章 Android的搜索引擎和Gtalk开发
  12.1 搜索引擎在手机中的应用
  12.1.1 本地搜索
  12.1.2 Web搜索
  12.2 Android搜索引擎API简介
  12.3 应用实例详解:过滤式搜索 引擎程序
  12.3.1 实例分析
  12.3.2 实例实现
  12.4 Android的GTalk应用开发
  12.4.1 GTalk在手机中的应用
  12.4.2 Android GTalk API简介
  12.4.3 为GTalk配置Android模拟器
  12.5 应用实例详解:Google GTalk 程序
  12.5.1 实例分析
  12.5.2 实例实现
第13章 Android综合案例开发:俄罗斯方块
  13.1 俄罗斯方块游戏功能需求
  13.2 俄罗斯方块游戏UI设计
  13.3 俄罗斯方块游戏功能实现
  13.4 俄罗斯方块游戏演示

百度网盘:http://pan.baidu.com/s/1c0lMrNq

 
2017-01-09 10:52:07 sinat_14899485 阅读数 711
  • Android移植基础

    Android视频课程,该课程可以让学员了解Android系统架构、学习如何下载Android源码、编译及开发Android、学习如何追踪Android源码、了解Linux内核启动流程、了解Android启动流程、学习如何移植外部函式库至Android源码中。

    26242 人正在学习 去看看 钟文昌

Android OpenGL ES 2.0学习研究 (一)

基于对 Google 的 Gallery 代码的研究和修改,对 OpenGL ES 2.0 在 Android 中的使用进行总结;

这一篇主要集中于四点进行简要介绍:GLRootView(base) + GLView(UI) + GLES20Canvas(canvas) + Texture;

关于OpenGL ES的基础知识可以参考:OpenGL ES 简明教程

概述:

目前,关于GLES的教程也有不少,但是基本上都是基础知识介绍,很零散;

Google官方的Gallery则对代码进行了封装,结构更加清晰灵活,非常适合学习研究GLES;

GLRootView(base)+ GLES20Canvas(canvas) + GLView(ui) + Texture:

  • GLRootView是一个GLSurfaceView,通过GLSurfaceView.Renderer的三大方法将GLView绘制到GLCanvas上:

    • GLSurfaceView:
      • 起到连接 OpenGL ES与Android 的 View 层次结构之间的桥梁作用。
      • 使得 Open GL ES 库适应于 Anndroid 系统的 Activity 生命周期。
      • 使得选择合适的 Frame buffer 像素格式变得容易。
      • 创建和管理单独绘图线程以达到平滑动画效果。
      • 提供了方便使用的调试工具来跟踪 OpenGL ES 函数调用以帮助检查错误。
      • public void setRenderer(GLSurfaceView.Renderer renderer)
    • GLSurfaceView.Renderer:

      • public void onSurfaceCreated(GL10 gl, EGLConfig config)
      • public void onDrawFrame(GL10 gl)
      • public void onSurfaceChanged(GL10 gl, int width, int height)
    • GLES20Canvas相当于Canvas,设置好Vertex shader和Fragment shader等参数,将GLView绘制出来:

    • GLES的使用都集中在这里处理,相当于从GLSurfaceView中抽离出来GLES的代码进行封装处理;
  • GLView是要绘制的UI,可以同时有多个,它处理触摸事件,通过GLRootView将其绘制在GLCanvas上:

    • GLView是整个UI的布局;
    • 可以在GLView基础上进行继承,充分自定义;
  • Texture则是绘制的画面,在GLES20Canvas上绘制出来:

    • 可以将其细分为ColorTexture、StringTexture、BitmapTexture分别绘制色块、字符串和图片;

接下来,看代码,具体说明看备注:

自定义一个GLRootView,继承GLSurfaceView并实现GLSurfaceView.Renderer接口(GLRoot为自定义接口)

//GLRoot为自定义接口
public class GLRootView extends GLSurfaceView
        implements GLSurfaceView.Renderer, GLRoot {

    public GLRootView(Context context) {
        this(context, null);
    }

    public GLRootView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //进行初始化设置
        setBackgroundDrawable(null);
        setEGLContextClientVersion(2);
        setEGLConfigChooser(mEglConfigChooser);
        setRenderer(this);
        if (Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
            getHolder().setFormat(PixelFormat.RGB_888);
        } else {
            getHolder().setFormat(PixelFormat.RGB_565);
        }
    }

    @Override
    public void onSurfaceCreated(GL10 gl1, EGLConfig config) {
        GL11 gl = (GL11) gl1;
        mRenderLock.lock();
        try {
            mGL = gl;

            //创建GLES20Canvas,创建的时候会自动加载shader
            mCanvas = new GLES20Canvas();

            BasicTexture.invalidateAllTextures();
        } finally {
            mRenderLock.unlock();
        }

        //设置渲染模式为 RENDERMODE_WHEN_DIRTY 以节约性能
        setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
      //setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }

    @Override
    public void onSurfaceChanged(GL10 gl1, int width, int height) {
        //设置线程
        Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
        GalleryUtils.setRenderThread();

        GL11 gl = (GL11) gl1;
        Utils.assertTrue(mGL == gl);

        //重新设置GLES20Canvas的尺寸
        mCanvas.setSize(width, height);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        AnimationTime.update();
        mRenderLock.lock();

        try {
            //重点在这,具体的绘制操作
        } finally {
            mRenderLock.unlock();
        }

        //第一次绘制的时候放置一个黑色的背景,以防透明
        if (mFirstDraw) {
            mFirstDraw = false;
            post(new Runnable() {
                    @Override
                    public void run() {
                        View root = getRootView();
                        View cover = root.findViewById(R.id.gl_root_cover);
                        cover.setVisibility(GONE);
                    }
                });
        }
    }

    //处理触摸事件
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        if (!isEnabled()) return false;

        int action = event.getAction();
        if (action == MotionEvent.ACTION_CANCEL
                || action == MotionEvent.ACTION_UP) {
            mInDownState = false;
        } else if (!mInDownState && action != MotionEvent.ACTION_DOWN) {
            return false;
        }

        mRenderLock.lock();
        try {
            // If this has been detached from root, we don't need to handle event
            boolean handled = mContentView != null
                    && mContentView.dispatchTouchEvent(event);
            if (action == MotionEvent.ACTION_DOWN && handled) {
                mInDownState = true;
            }
            return handled;
        } finally {
            mRenderLock.unlock();
        }
    }
}

自定义GLES20Canvas


@SuppressLint("NewApi")
public class GLES20Canvas implements GLCanvas {

        private abstract static class ShaderParameter {
        public int handle;
        protected final String mName;

        public ShaderParameter(String name) {
            mName = name;
        }

        public abstract void loadHandle(int program);
    }

    //处理shader
    private static class UniformShaderParameter extends ShaderParameter {
        public UniformShaderParameter(String name) {
            super(name);
        }

        @Override
        public void loadHandle(int program) {
            handle = GLES20.glGetUniformLocation(program, mName);
            checkError();
        }
    }

    private static class AttributeShaderParameter extends ShaderParameter {
        public AttributeShaderParameter(String name) {
            super(name);
        }

        @Override
        public void loadHandle(int program) {
            handle = GLES20.glGetAttribLocation(program, mName);
            checkError();
        }
    }

    //初始化
    public GLES20Canvas() {
        Matrix.setIdentityM(mTempTextureMatrix, 0);
        Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex);

        FloatBuffer boxBuffer = createBuffer(BOX_COORDINATES);
        mBoxCoordinates = uploadBuffer(boxBuffer);

        //创建的时候就加载shader
        int drawVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, DRAW_VERTEX_SHADER);
        int textureVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, TEXTURE_VERTEX_SHADER);
        int meshVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, MESH_VERTEX_SHADER);
        int drawFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, DRAW_FRAGMENT_SHADER);
        int textureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, TEXTURE_FRAGMENT_SHADER);
        int oesTextureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
                OES_TEXTURE_FRAGMENT_SHADER);

        mDrawProgram = assembleProgram(drawVertexShader, drawFragmentShader, mDrawParameters);
        mTextureProgram = assembleProgram(textureVertexShader, textureFragmentShader,
                mTextureParameters);
        mOesTextureProgram = assembleProgram(textureVertexShader, oesTextureFragmentShader,
                mOesTextureParameters);
        mMeshProgram = assembleProgram(meshVertexShader, textureFragmentShader, mMeshParameters);
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
        checkError();
    }

    @Override
    public void setSize(int width, int height) {
        mWidth = width;
        mHeight = height;
        GLES20.glViewport(0, 0, mWidth, mHeight);
        checkError();
        Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex);
        Matrix.orthoM(mProjectionMatrix, 0, 0, width, 0, height, -1, 1);
        if (getTargetTexture() == null) {
            mScreenWidth = width;
            mScreenHeight = height;
            Matrix.translateM(mMatrices, mCurrentMatrixIndex, 0, height, 0);
            Matrix.scaleM(mMatrices, mCurrentMatrixIndex, 1, -1, 1);
        }
    }

    private void draw(int type, int offset, int count, float x, float y, float width, float height,
            int color, float lineWidth) {
        prepareDraw(offset, color, lineWidth);
        draw(mDrawParameters, type, count, x, y, width, height);
    }

    //设置背景颜色
    private void prepareDraw(int offset, int color, float lineWidth) {
        GLES20.glUseProgram(mDrawProgram);
        checkError();
        if (lineWidth > 0) {
            GLES20.glLineWidth(lineWidth);
            checkError();
        }
        float[] colorArray = getColor(color);
        boolean blendingEnabled = (colorArray[3] < 1f);
        enableBlending(blendingEnabled);
        if (blendingEnabled) {
            GLES20.glBlendColor(colorArray[0], colorArray[1], colorArray[2], colorArray[3]);
            checkError();
        }

        GLES20.glUniform4fv(mDrawParameters[INDEX_COLOR].handle, 1, colorArray, 0);
        setPosition(mDrawParameters, offset);
        checkError();
    }

    //绘制
    private void draw(ShaderParameter[] params, int type, int count, float x, float y, float width,
            float height) {
        setMatrix(params, x, y, width, height);
        int positionHandle = params[INDEX_POSITION].handle;
        GLES20.glEnableVertexAttribArray(positionHandle);
        checkError();
        GLES20.glDrawArrays(type, 0, count);
        checkError();
        GLES20.glDisableVertexAttribArray(positionHandle);
        checkError();
    }


    public static void checkError() {
        int error = GLES20.glGetError();
        if (error != 0) {
            Throwable t = new Throwable();
            Log.e(TAG, "GL error: " + error, t);
        }
    }


    //以下几个方法均为BitmapTexture调用
    @Override
    public void setTextureParameters(BasicTexture texture) {
        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    }

    @Override
    public void initializeTextureSize(BasicTexture texture, int format, int type) {
        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        int width = texture.getTextureWidth();
        int height = texture.getTextureHeight();
        GLES20.glTexImage2D(target, 0, format, width, height, 0, format, type, null);
    }

    @Override
    public void initializeTexture(BasicTexture texture, Bitmap bitmap) {
        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        GLUtils.texImage2D(target, 0, bitmap, 0);
    }

    @Override
    public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap,
            int format, int type) {
        int target = texture.getTarget();
        GLES20.glBindTexture(target, texture.getId());
        checkError();
        GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type);
    }
}

自定义GLView

public class GLView {

    public void startAnimation(CanvasAnimation animation) {
        GLRoot root = getGLRoot();
        if (root == null) throw new IllegalStateException();
        mAnimation = animation;
        if (mAnimation != null) {
            mAnimation.start();
            root.registerLaunchedAnimation(mAnimation);
        }
        invalidate();
    }

    // Sets the visiblity of this GLView (either GLView.VISIBLE or
    // GLView.INVISIBLE).
    public void setVisibility(int visibility) {
        if (visibility == getVisibility()) return;
        if (visibility == VISIBLE) {
            mViewFlags &= ~FLAG_INVISIBLE;
        } else {
            mViewFlags |= FLAG_INVISIBLE;
        }
        onVisibilityChanged(visibility);
        invalidate();
    }

    // Returns GLView.VISIBLE or GLView.INVISIBLE
    public int getVisibility() {
        return (mViewFlags & FLAG_INVISIBLE) == 0 ? VISIBLE : INVISIBLE;
    }

    // This should only be called on the content pane (the topmost GLView).
    public void attachToRoot(GLRoot root) {
        Utils.assertTrue(mParent == null && mRoot == null);
        onAttachToRoot(root);
    }

    // This should only be called on the content pane (the topmost GLView).
    public void detachFromRoot() {
        Utils.assertTrue(mParent == null && mRoot != null);
        onDetachFromRoot();
    }

    // Returns the number of children of the GLView.
    public int getComponentCount() {
        return mComponents == null ? 0 : mComponents.size();
    }

    // Returns the children for the given index.
    public GLView getComponent(int index) {
        if (mComponents == null) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        return mComponents.get(index);
    }

    // Adds a child to this GLView.
    public void addComponent(GLView component) {
        // Make sure the component doesn't have a parent currently.
        if (component.mParent != null) throw new IllegalStateException();

        // Build parent-child links
        if (mComponents == null) {
            mComponents = new ArrayList<GLView>();
        }
        mComponents.add(component);
        component.mParent = this;

        // If this is added after we have a root, tell the component.
        if (mRoot != null) {
            component.onAttachToRoot(mRoot);
        }
    }

    // Removes a child from this GLView.
    public boolean removeComponent(GLView component) {
        if (mComponents == null) return false;
        if (mComponents.remove(component)) {
            removeOneComponent(component);
            return true;
        }
        return false;
    }

    // Removes all children of this GLView.
    public void removeAllComponents() {
        for (int i = 0, n = mComponents.size(); i < n; ++i) {
            removeOneComponent(mComponents.get(i));
        }
        mComponents.clear();
    }

    private void removeOneComponent(GLView component) {
        if (mMotionTarget == component) {
            long now = SystemClock.uptimeMillis();
            MotionEvent cancelEvent = MotionEvent.obtain(
                    now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0);
            dispatchTouchEvent(cancelEvent);
            cancelEvent.recycle();
        }
        component.onDetachFromRoot();
        component.mParent = null;
    }

    public Rect bounds() {
        return mBounds;
    }

    public int getWidth() {
        return mBounds.right - mBounds.left;
    }

    public int getHeight() {
        return mBounds.bottom - mBounds.top;
    }

    public GLRoot getGLRoot() {
        return mRoot;
    }

    // Request re-rendering of the view hierarchy.
    // This is used for animation or when the contents changed.
    public void invalidate() {
        GLRoot root = getGLRoot();
        if (root != null) root.requestRender();
    }

    // Request re-layout of the view hierarchy.
    public void requestLayout() {
        mViewFlags |= FLAG_LAYOUT_REQUESTED;
        mLastHeightSpec = -1;
        mLastWidthSpec = -1;
        if (mParent != null) {
            mParent.requestLayout();
        } else {
            // Is this a content pane ?
            GLRoot root = getGLRoot();
            if (root != null) root.requestLayoutContentPane();
        }
    }

    protected void render(GLCanvas canvas) {
        boolean transitionActive = false;
        if (mTransition != null && mTransition.calculate(AnimationTime.get())) {
            invalidate();
            transitionActive = mTransition.isActive();
        }
        renderBackground(canvas);
        canvas.save();
        if (transitionActive) {
            mTransition.applyContentTransform(this, canvas);
        }
        for (int i = 0, n = getComponentCount(); i < n; ++i) {
            renderChild(canvas, getComponent(i));
        }
        canvas.restore();
        if (transitionActive) {
            mTransition.applyOverlay(this, canvas);
        }
    }

    public void setIntroAnimation(StateTransitionAnimation intro) {
        mTransition = intro;
        if (mTransition != null) mTransition.start();
    }

    public float [] getBackgroundColor() {
        return mBackgroundColor;
    }

    public void setBackgroundColor(float [] color) {
        mBackgroundColor = color;
    }

    protected void renderBackground(GLCanvas view) {
        if (mBackgroundColor != null) {
            view.clearBuffer(mBackgroundColor);
        }
        if (mTransition != null && mTransition.isActive()) {
            mTransition.applyBackground(this, view);
            return;
        }
    }

    protected void renderChild(GLCanvas canvas, GLView component) {
        if (component.getVisibility() != GLView.VISIBLE
                && component.mAnimation == null) return;

        int xoffset = component.mBounds.left - mScrollX;
        int yoffset = component.mBounds.top - mScrollY;

        canvas.translate(xoffset, yoffset);

        CanvasAnimation anim = component.mAnimation;
        if (anim != null) {
            canvas.save(anim.getCanvasSaveFlags());
            if (anim.calculate(AnimationTime.get())) {
                invalidate();
            } else {
                component.mAnimation = null;
            }
            anim.apply(canvas);
        }
        component.render(canvas);
        if (anim != null) canvas.restore();
        canvas.translate(-xoffset, -yoffset);
    }

    protected boolean onTouch(MotionEvent event) {
        return false;
    }

    protected boolean dispatchTouchEvent(MotionEvent event,
            int x, int y, GLView component, boolean checkBounds) {
        Rect rect = component.mBounds;
        int left = rect.left;
        int top = rect.top;
        if (!checkBounds || rect.contains(x, y)) {
            event.offsetLocation(-left, -top);
            if (component.dispatchTouchEvent(event)) {
                event.offsetLocation(left, top);
                return true;
            }
            event.offsetLocation(left, top);
        }
        return false;
    }

    protected boolean dispatchTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        int action = event.getAction();
        if (mMotionTarget != null) {
            if (action == MotionEvent.ACTION_DOWN) {
                MotionEvent cancel = MotionEvent.obtain(event);
                cancel.setAction(MotionEvent.ACTION_CANCEL);
                dispatchTouchEvent(cancel, x, y, mMotionTarget, false);
                mMotionTarget = null;
            } else {
                dispatchTouchEvent(event, x, y, mMotionTarget, false);
                if (action == MotionEvent.ACTION_CANCEL
                        || action == MotionEvent.ACTION_UP) {
                    mMotionTarget = null;
                }
                return true;
            }
        }
        if (action == MotionEvent.ACTION_DOWN) {
            // in the reverse rendering order
            for (int i = getComponentCount() - 1; i >= 0; --i) {
                GLView component = getComponent(i);
                if (component.getVisibility() != GLView.VISIBLE) continue;
                if (dispatchTouchEvent(event, x, y, component, true)) {
                    mMotionTarget = component;
                    return true;
                }
            }
        }
        return onTouch(event);
    }

    public Rect getPaddings() {
        return mPaddings;
    }

    public void layout(int left, int top, int right, int bottom) {
        boolean sizeChanged = setBounds(left, top, right, bottom);
        mViewFlags &= ~FLAG_LAYOUT_REQUESTED;
        // We call onLayout no matter sizeChanged is true or not because the
        // orientation may change without changing the size of the View (for
        // example, rotate the device by 180 degrees), and we want to handle
        // orientation change in onLayout.
        onLayout(sizeChanged, left, top, right, bottom);
    }

    private boolean setBounds(int left, int top, int right, int bottom) {
        boolean sizeChanged = (right - left) != (mBounds.right - mBounds.left)
                || (bottom - top) != (mBounds.bottom - mBounds.top);
        mBounds.set(left, top, right, bottom);
        return sizeChanged;
    }

    public void measure(int widthSpec, int heightSpec) {
        if (widthSpec == mLastWidthSpec && heightSpec == mLastHeightSpec
                && (mViewFlags & FLAG_LAYOUT_REQUESTED) == 0) {
            return;
        }

        mLastWidthSpec = widthSpec;
        mLastHeightSpec = heightSpec;

        mViewFlags &= ~FLAG_SET_MEASURED_SIZE;
        onMeasure(widthSpec, heightSpec);
        if ((mViewFlags & FLAG_SET_MEASURED_SIZE) == 0) {
            throw new IllegalStateException(getClass().getName()
                    + " should call setMeasuredSize() in onMeasure()");
        }
    }

    protected void onMeasure(int widthSpec, int heightSpec) {
    }

    protected void setMeasuredSize(int width, int height) {
        mViewFlags |= FLAG_SET_MEASURED_SIZE;
        mMeasuredWidth = width;
        mMeasuredHeight = height;
    }

    public int getMeasuredWidth() {
        return mMeasuredWidth;
    }

    public int getMeasuredHeight() {
        return mMeasuredHeight;
    }

    protected void onLayout(
            boolean changeSize, int left, int top, int right, int bottom) {
    }

    /**
     * Gets the bounds of the given descendant that relative to this view.
     */
    public boolean getBoundsOf(GLView descendant, Rect out) {
        int xoffset = 0;
        int yoffset = 0;
        GLView view = descendant;
        while (view != this) {
            if (view == null) return false;
            Rect bounds = view.mBounds;
            xoffset += bounds.left;
            yoffset += bounds.top;
            view = view.mParent;
        }
        out.set(xoffset, yoffset, xoffset + descendant.getWidth(),
                yoffset + descendant.getHeight());
        return true;
    }

    protected void onVisibilityChanged(int visibility) {
        for (int i = 0, n = getComponentCount(); i < n; ++i) {
            GLView child = getComponent(i);
            if (child.getVisibility() == GLView.VISIBLE) {
                child.onVisibilityChanged(visibility);
            }
        }
    }

    protected void onAttachToRoot(GLRoot root) {
        mRoot = root;
        for (int i = 0, n = getComponentCount(); i < n; ++i) {
            getComponent(i).onAttachToRoot(root);
        }
    }

    protected void onDetachFromRoot() {
        for (int i = 0, n = getComponentCount(); i < n; ++i) {
            getComponent(i).onDetachFromRoot();
        }
        mRoot = null;
    }

    public void lockRendering() {
        if (mRoot != null) {
            mRoot.lockRenderThread();
        }
    }

    public void unlockRendering() {
        if (mRoot != null) {
            mRoot.unlockRenderThread();
        }
    }
}

自定义Texture

ColorTexture


// ColorTexture 就是一个填充特定颜色的色块,代码很简单,包括颜色和尺寸,已经绘制的方法;
public class ColorTexture implements Texture {

    private final int mColor;
    private int mWidth;
    private int mHeight;

    public ColorTexture(int color) {
        mColor = color;
        mWidth = 1;
        mHeight = 1;
    }

    @Override
    public void draw(GLCanvas canvas, int x, int y) {
        draw(canvas, x, y, mWidth, mHeight);
    }

    @Override
    public void draw(GLCanvas canvas, int x, int y, int w, int h) {
        canvas.fillRect(x, y, w, h, mColor);
    }

    @Override
    public boolean isOpaque() {
        return Utils.isOpaque(mColor);
    }

    public void setSize(int width, int height) {
        mWidth = width;
        mHeight = height;
    }

    @Override
    public int getWidth() {
        return mWidth;
    }

    @Override
    public int getHeight() {
        return mHeight;
    }
}

StringTexture


// StringTexture 提供了文本内容的绘制方法,可以设置文本内容、字体大小,颜色,也很简单;
public class StringTexture extends CanvasTexture {
    private final String mText;
    private final TextPaint mPaint;
    private final FontMetricsInt mMetrics;

    private StringTexture(String text, TextPaint paint,
            FontMetricsInt metrics, int width, int height) {
        super(width, height);
        mText = text;
        mPaint = paint;
        mMetrics = metrics;
    }

    public static TextPaint getDefaultPaint(float textSize, int color) {
        TextPaint paint = new TextPaint();
        paint.setTextSize(textSize);
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setShadowLayer(2f, 0f, 0f, Color.BLACK);
        return paint;
    }

    public static StringTexture newInstance(
            String text, float textSize, int color) {
        return newInstance(text, getDefaultPaint(textSize, color));
    }

    public static StringTexture newInstance(
            String text, float textSize, int color,
            float lengthLimit, boolean isBold) {
        TextPaint paint = getDefaultPaint(textSize, color);
        if (isBold) {
            paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
        }
        if (lengthLimit > 0) {
            text = TextUtils.ellipsize(
                    text, paint, lengthLimit, TextUtils.TruncateAt.END).toString();
        }
        return newInstance(text, paint);
    }

    private static StringTexture newInstance(String text, TextPaint paint) {
        FontMetricsInt metrics = paint.getFontMetricsInt();
        int width = (int) Math.ceil(paint.measureText(text));
        int height = metrics.bottom - metrics.top;
        // The texture size needs to be at least 1x1.
        if (width <= 0) width = 1;
        if (height <= 0) height = 1;
        return new StringTexture(text, paint, metrics, width, height);
    }

    @Override
    protected void onDraw(Canvas canvas, Bitmap backing) {
        canvas.translate(0, -mMetrics.ascent);
        canvas.drawText(mText, 0, 0, mPaint);
    }
}

BitmapTexture


// BitmapTexture 提供了图片的绘制方法,细节都在UploadedTexture里,这是处理起来最麻烦的Texture了
public class BitmapTexture extends UploadedTexture {
    protected Bitmap mContentBitmap;

    public BitmapTexture(Bitmap bitmap) {
        this(bitmap, false);
    }

    public BitmapTexture(Bitmap bitmap, boolean hasBorder) {
        super(hasBorder);
        Assert.assertTrue(bitmap != null && !bitmap.isRecycled());
        mContentBitmap = bitmap;
    }

    @Override
    protected void onFreeBitmap(Bitmap bitmap) {
        if (!inFinalizer()) {
            bitmap.recycle();
        }
    }

    @Override
    protected Bitmap onGetBitmap() {
        return mContentBitmap;
    }

    public Bitmap getBitmap() {
        return mContentBitmap;
    }
}

说明

下一篇会细化介绍

2013-01-28 10:20:52 iteye_10107 阅读数 28
  • Android移植基础

    Android视频课程,该课程可以让学员了解Android系统架构、学习如何下载Android源码、编译及开发Android、学习如何追踪Android源码、了解Linux内核启动流程、了解Android启动流程、学习如何移植外部函式库至Android源码中。

    26242 人正在学习 去看看 钟文昌
资料名称
下载地址
《软件框架设计的艺术》(Practical API Design)【英文原版PDF】
http://down.51cto.com/data/173728
Java零基础学习程序设计+帮助文档(适合初学者)
http://down.51cto.com/data/636058
[Android开发书籍]Learn Java for Android Development
http://down.51cto.com/data/614721
Guide to Web Development With Java Understanding Website
http://down.51cto.com/data/606167
Packt.Java.7.Concurrency.Cookbook【英文电子书】
http://down.51cto.com/data/602396
JAVA编程思想中文第3版【PDF】
http://down.51cto.com/data/581648
数据结构与算法-JAVA语言版【PDF】
http://down.51cto.com/data/348618
JDBC的高级数据库操作【CHM电子书】
http://down.51cto.com/data/454738
《Java程序员,上班那些事儿》Java程序员职业指导电子书
http://down.51cto.com/data/465533
JAVA开发利器My Eclipse全面详解【PDF电子书】
http://down.51cto.com/data/461351
【JAVA资料免豆下载】158个JAVA免豆资料汇总(下载目录)
http://down.51cto.com/data/431561
Hadoop源代码分析(完整版).pdf
http://down.51cto.com/data/231113
【珍藏版】2012java开发工程师必备精品资料(115个)
http://down.51cto.com/data/417852
《开发月刊》2012年5月刊总第14期:Java开发与JVM
http://down.51cto.com/data/413573
《Java开发利器Myeclipse全面详解》PDF版电子书
http://down.51cto.com/data/400216
《JAVA2核心技术第7版卷I卷Ⅱ书》英文版CHM下载
http://down.51cto.com/data/411344
maven、java敏捷开发、freemarkerPDF版电子书
http://down.51cto.com/data/234347
写给大家看的面向对象编程书
http://down.51cto.com/data/332373
《Hadoop实战》分布式架构中文电子书
http://down.51cto.com/data/316832
《深入浅出 EJB(中文版)》PDF电子书
http://down.51cto.com/data/259353
《JAVA并发编程实践》PDF版电子书
http://down.51cto.com/data/251343
Spring 3.X 权威开发指南:实施Jave EE 6的利器
http://down.51cto.com/data/259169
《精通Struts:基于MVC的Java Web设计与开发》高清电子书
http://down.51cto.com/data/256121
《Java技术手册(第三版)》中文电子书
http://down.51cto.com/data/254675
《Java核心技术卷I 基础知识(原书第8版)》电子书
http://down.51cto.com/data/253012
《J2EE设计开发编程指南》中文 (PDF)
http://down.51cto.com/data/252052
《精通Spring》清晰书签版电子书
http://down.51cto.com/data/250227
《Java测试与设计:从单元测试到自动Web测试》清晰电子书
http://down.51cto.com/data/248972
深入体验JAVA Web开发内幕-高级特性(亲测完整)
http://down.51cto.com/data/242327
《实用J2EE设计模式编程指南》完整电子书
http://down.51cto.com/data/233919
Java开发技术电子书30本合集
这份合集中收集了30本Java开发方面的电子书,对Java语言及其主要的API进行了精辟的介绍,,涵盖中文版、英文原版以及各种实用手册,经验丰富的程序员可以借此立即开始编写Java代码。
2014-07-25 10:09:00 weixin_30532837 阅读数 3
  • Android移植基础

    Android视频课程,该课程可以让学员了解Android系统架构、学习如何下载Android源码、编译及开发Android、学习如何追踪Android源码、了解Linux内核启动流程、了解Android启动流程、学习如何移植外部函式库至Android源码中。

    26242 人正在学习 去看看 钟文昌

        我们刚开始学新东西的时候,往往希望能从一个实例进行入手学习。接下来的系列连载文章也主要是围绕这个实例进行。这个实例原形是从电子书《Android应用开发详解》得到的,我们在这里对其进行详细的解释,并对Android的一些基础知识穿插进去,并对该例子进行一些新的扩充。

        本节说阐述的很多内容可能与Android相关性并不大,但是本节确实之后的基础,也是想从一个系统架构方面来体现Anroid在一个系统之后所担当的职责。在我现在的理解之中,Android在一系统之中,其承担的职责是前端的展示以及一些逻辑的简单处理,就好比是一个浏览器,包括IOS所负责的也是前端内容的展示。(当然,如果你所做的是无关互联网的APP,如本地Anroid一些游戏的开发则另当别论)。

 

一.需求分析

        该例子是一个无线点餐系统。简单来分析一些该系统的需求分析。在一个大的餐馆当中,面对很多的顾客,为了方便顾客点餐,提升饭店的效率,需一个无限终端实现对顾客的点餐。也就是说由一个无线客户端负责对点餐,还需有一个PC用来进行结账以及打印工作。

 

二.技术选型

       下面具体来看我们的技术选型。

       无线客户端我们使用Android客户端,网络通信部分我们使用Apache Http协议客户端,中间Web服务器采用Servlet响应客户端请求。后台数据库采用JDBC访问数据库,数据库我们采用MySql,部分存储我们使用本地的SqlLite数据库(这里涉及到MySql与SqlLite的数据同步问题),结账以及打印功能我们采取WPF去做。

       看了以上这些技术,你可能会感觉有点晕,但是实现起来并没有我们想象的那么困难,之后的文章会对各个技术进行详细阐述。

 

三.系统功能

       首先我们来看Android客户端所需实现的功能。

       1.系统的登陆功能

              每个系统都会有一个入口,即登陆。通过登陆可以进入系统的主菜单,转而使用其他功能。

      2.点餐功能

              该功能也是我们系统之中的核心功能。该功能有操作员来完成,通过输入顾客的点餐信息,通过无线网络将数据保存到系统后台的服务器当中,进而在厨房的终端进行显示。该功能主要包括三个部分:开桌,点菜和下单。

      3.查台功能

            即当顾客进行点餐的时候,需要首先查询有哪些桌子是空的,才可安排顾客进行就餐。

     4.更新功能

           为了提高程序的运行效率。我们需要将部分数据保存的手机本地的SqlLite数据库中,在此系统之中,我们需要将菜单以及桌子号码的数据保存到SqlLite数据库当中,因此当后台数据库更新菜单以及桌号时,我们自然也需要将该数据同步更新到本地SqlLite数据库当中。

    5.转台功能

       转台功能是指当顾客下单之后,又要求更换座位,我们这时需要将已经保存到数据库中的数据进行更新。(说白了,就是对订单的修改)

    6.并台功能

        并台功能是指将已经下单的两组顾客合并到同一桌子上。该功能也需要修改已经提交给服务器数据。

    我们再来看看PC客户端所要实现的功能。

     1.登陆功能

        PC客户端的登陆。

     2.结账功能

          当顾客付完钱后,实现对订单的结账。

     3.打印功能

          对订单的打印。

     4.对服务员的增删改查。

           即如果餐馆新增一名服务员,则需要新添加一个新的账号,给服务员使用。

 

四.系统的详细设计

     1.数据库的设计

 

      Anroid客户端下的系统架构如下。

      1.系统包资源的规划(就相当于我们在VS下,一个解决方案由哪些类库组成)

           本系统的主要功能可以分为三类:一是访问客户端SqlLite的数据库;二是Activity界面展示;三是通过网络访问服务器数据。

                                                   表1     系统包说明

           包名称             包描述
com.golook.provider 访问本地SqlLite数据库的Provider
com.golook.util 工具类包
com.golook.wlo Activity包

         对于PC客户端的设计,因为使用到的是.Net技术,相信大家都很熟悉,在之后的文章中会提及,这里就不再累述。

    2.数据库的设计

         之前我们提过,数据库的设计架构是服务端采用MySql数据库(我自己搭建的数据库是MySql5.7),Android客户端的数据库采用的是自身的SqlLite数据库。两个数据库之间存在着数据库的更新,而使其可以保持一致。下来我们具体来看看是如何设计表。

            1.系统用户表(usertbl),登陆系统使用

Field Name Fielt Type Size Comment
id Integer 11 主键,自动增长
account Varchar 20 登陆账号
password Varchar 20 登陆密码
name Varchar 20 姓名
gender Varchar 20 性别
permission Integer 11 权限 1-管理员 2-收银员 3-服务员
remark Varchar 200 备注

            2.菜谱分类表(menutypetbl)。将菜单信息分类,如热菜,凉菜,海鲜等等。

Field Name Fielt Type Size Comment
id Integer 11 主键,自动增长
name Varchar 20 类型名称

             3.菜谱表(menutbl),用来保存菜的基本信息。

Field Name Fielt Type Size Comment
id Integer 11 主键,自增长
typeId Integer 11 外键,引用外键,引用菜谱分类表Id
name Varchar 20 名称
price Integer 11 价格
pic Varchar 100 图片路径
remark Varchar 200 备注

              4.餐桌表(tabletbl)。用来表示顾客在哪个座位就餐。

            

Field Name Fielt Type Size Comment
id Integer 11 主键,自增长
num Integer 11 桌号
flag Integer 11 餐桌状态 0-空桌子 1-有人就餐
description Varchar 100 描述

 

     5.订单表(OrderTbl)。

Field Name Fielt Type Size Comment
id Integer 11 主键,自增长
orderTime Varchar 30 下单时间
userId Interger 11 下单用户,外键-系统用户表Id
tableId Integer 11 桌号,外键-桌号的Id
personNum Integer 11 人数
isPay Integer 11 是否结算 0-未结算 1-结算
remark Varchar 200 备注

               6.订单明细表(OrderDetailTbl),与订单表是一对多的关系。

Field Name Fielt Type Size Comment
id Integer 11 主键,自增长
orderId Interger 11 外键,参照订单Id
menuId Integer 11 外键,参照菜谱Id
num Integer 11 数量
remark Integer 11 备注

这是数据库的大概设计,在文末我会把MySql的数据库脚本放置出来,供大家下载。

下节会从Android的界面讲起,直到能完成登陆功能。

该无限点餐系统数据库Sql脚本。点击此处下载

转载于:https://www.cnblogs.com/yanfengfree/p/3867327.html

没有更多推荐了,返回首页