谷歌安卓开发指南

移动开发 Android
安卓是一种以Linux为基础的开放源码操作系统,主要使用于便携设备。目前尚未有统一中文名称,中国大陆地区较多人使用“安卓”。安卓被谷歌收购之后,发展迅速,谷歌安卓开发已经成为手机开发中最重要的一个平台。

安卓操作系统最初由Andy Rubin开发,最初主要支持手机。2005年由Google收购注资,并组建开放手机联盟开发改良,逐渐扩展到平板电脑及其他领域上。安卓的主要竞争对手是苹果公司的iOS以及RIM的Blackberry OS。2011年第一季度,安卓在全球的市场份额首次超过塞班系统,跃居全球第一。 2012年2月数据,安卓占据全球智能手机操作系统市场52.5%的份额,中国市场占有率为68.4%。

安卓用甜点作为它们系统版本的代号的命名方法开始于 安卓 1.5 发布的时候。作为每个版本代表的甜点的尺寸越变越大,然后按照26个字母数序:纸杯蛋糕,甜甜圈,松饼,冻酸奶,姜饼,蜂巢,冰激凌三明治,根据最新消息新一代安卓版本将命名为果冻豆(Jelly Bean)。

架构

谷歌安卓的系统架构和其它操作系统一样,采用了分层的架构。从架构图看,谷歌安卓分为四个层,从高层到低层分别是应用程序层、应用程序框架层、系统运行库层和linux核心层。

谷歌安卓是以Linux为核心的手机操作平台,作为一款开放式的操作系统,随着谷歌安卓的快速发展,如今已允许开发者使用多种编程语言来开发谷歌安卓应用程序,而不再是以前只能使用Java开发谷歌安卓应用程序的单一局面,因而受到众多开发者的欢迎,成为真正意义上的开放式操作系统。

在谷歌安卓中,开发者可以使用Java作为编程语言来开发应用程序,也可以通过NDK使用C/C++作为编程语言来开发应用程序,也可使用SL4A来使用其他各种脚本语言进行编程(如:python、lua、tcl、php等等),还有其他诸如:Qt(qt for 谷歌安卓)、Mono(mono for 谷歌安卓)等一些著名编程框架也开始支持谷歌安卓编程,甚至通过MonoDroid,开发者还可以使用C#作为编程语言来开发应用程序。另外,谷歌还在2009年特别发布了针对初学者的谷歌安卓 Simple语言,该语言类似Basic语言。而在网页编程语言方面,JavaScript,ajax,HTML5,jquery、sencha、dojo、mobl、PhoneGap等等都已经支持谷歌安卓开发。

而在谷歌安卓系统底层方面,谷歌安卓使用C/C++作为开发语言。

应用程序(部分)

早期的谷歌安卓应用程序开发,通常通过谷歌安卓 SDK(谷歌安卓软件开发包)下使用Java作为编程语言来开发应用程序,但通过不同的软件开发包,则使用的编程语言也不同。

例如开发者可以通过谷歌安卓 NDK(谷歌安卓 Native开发包)使用C语言或者C++语言来作为编程语言开发应用程序。同时谷歌还推出了适合初学者编程使用的Simple语言,该语言类似微软公司的Visual Basic语言。此外,谷歌公司还推出了Google App Inventor开发工具,该开发工具可以快速地构建应用程序,方便新手开发者。

Java开发方面

谷歌安卓支持使用Java作为编程语言来开发应用程序,而谷歌安卓的Java开发方面从接口到功能,都有层出不穷的变化。考虑到Java虚拟机的效率和资源占用,谷歌重新设计了谷歌安卓的Java,以便能提高效率和减少资源占用,因而与J2ME等不同。 谷歌安卓结构其中Activity等同于J2ME的MIDlet,一个 Activity 类(Class)负责创建视窗(Windows),一个活动中的Activity就是在 foreground(前景)模式,背景运行的程序叫做Service。两者之间通过由ServiceConnection和AIDL连结,达到复数程序同时运行效果。如果运行中的 Activity 全部画面被其他 Activity 取代时,该 Activity 便被停止(Stopped),甚至被系统清除(Kill)。

View等同于J2ME的Displayable,程序人员可以通过 View 类与“XML layout”档将UI放置在视窗上,谷歌安卓 1.5的版本可以利用 View 打造出所谓的 Widgets,其实Widget只是View的一种,所以可以使用xml来设计layout,HTC的谷歌安卓 Hero手机即含有大量的widget。至于ViewGroup 是各种layout 的基础抽象类(abstract class),ViewGroup之内还可以有ViewGroup。View的构造函数不需要再Activity中调用,但是Displayable的是必须的,在Activity 中,要通过findViewById()来从XML 中取得View,谷歌安卓的View类的显示很大程度上是从XML中读取的。View 与事件(event)息息相关,两者之间通过Listener 结合在一起,每一个View都可以注册一个event listener,例如:当View要处理用户触碰(touch)的事件时,就要向谷歌安卓框架注册View.OnClickListener。另外还有BitMap等同于J2ME的Image。

C/C++开发方面

早期的谷歌安卓开发只支持Java作为编程语言开发应用程序,因而使得其他语言开发者只能望而却步。2010年4月,谷歌正式对开发者发布了谷歌安卓 NDK,NDK允许开发者使用C/C++作为编程语言来为谷歌安卓开发应用程序,初版的NDK使得开发者看到了C/C++在谷歌安卓开发中的希望。

但是,当前版本的NDK在功能上还有很多局限性:NDK并没有提供对应用程序生命周期的维护;NDK也不提供对谷歌安卓系统中大量系统事件的支持;对于作为应用程序交互接口的UI API,当前版本的NDK中也没有提供。但是相对于初版的NDK,现在的NDK已经进行了许多重大的功能改进。

由此可见,NDK仍然需要完善和发展,相信未来随着NDK的发展,NDK可以做得更多更好。

中介软件

操作系统与应用程序的沟通桥梁,应用分为两层:函数层(Library)和虚拟机(Virtual Machine)。 Bionic是 谷歌安卓 改良libc的版本。谷歌安卓 同时包含了Webkit,所谓的Webkit 就是Apple Safari 浏览器背后的引擎。Surface flinger 是就2D或3D的内容显示到屏幕上。谷歌安卓使用工具链(Toolchain)为Google自制的Bionic Libc。

谷歌安卓采用OpenCORE作为基础多媒体框架。OpenCORE可分7大块:PVPlayer、PVAuthor、Codec、PacketVideo Multimedia Framework(PVMF)、Operating System Compatibility Library(OSCL)、Common、OpenMAX。

谷歌安卓 使用skia 为核心图形引擎,搭配OpenGL/ES。skia与Linux Cairo功能相当,但相较于Linux Cairo, skia 功能还只是雏形的。2005年Skia公司被Google收购,2007年初,Skia GL源码被公开,目前Skia 也是Google Chrome 的图形引擎。

谷歌安卓的多媒体数据库采用SQLite数据库系统。数据库又分为共用数据库及私用数据库。用户可通过ContentResolver类(Column)取得共用数据库。

谷歌安卓的中间层多以Java 实现,并且采用特殊的Dalvik 虚拟机(Dalvik Virtual Machine)。Dalvik虚拟机是一种“暂存器型态”(Register Based)的Java虚拟机,变量皆存放于暂存器中,虚拟机的指令相对减少。

Dalvik虚拟机可以有多个实例(instance), 每个谷歌安卓应用程序都用一个自属的Dalvik虚拟机来运行,让系统在运行程序时可达到优化。Dalvik 虚拟机并非运行Java字节码(Bytecode),而是运行一种称为.dex格式的文件。

硬件抽像层

谷歌安卓 的 HAL(硬件抽像层)是能以封闭源码形式提供硬件驱动模块。HAL 的目的是为了把 谷歌安卓 framework 与 Linux kernel 隔开,让 谷歌安卓 不至过度依赖 Linux kernel,以达成 kernel independent 的概念,也让 谷歌安卓 framework 的开发能在不考量驱动程序实现的前提下进行发展。

HAL stub 是一种代理人(proxy)的概念,stub 是以 *.so 档的形式存在。Stub 向 HAL“提供”操作函数(operations),并由 谷歌安卓 runtime 向 HAL 取得 stub 的 operations,再 callback 这些操作函数。HAL 里包含了许多的 stub(代理人)。Runtime 只要说明“类型”,即 module ID,就可以取得操作函数。

内核

谷歌安卓 是运行于 Linux kernel之上,但并不是GNU/Linux。因为在一般GNU/Linux 里支持的功能,谷歌安卓 大都没有支持,包括Cairo、X11、Alsa、FFmpeg、GTK、Pango及Glibc等都被移除掉了。谷歌安卓又以bionic 取代Glibc、以Skia 取代Cairo、再以opencore 取代FFmpeg 等等。谷歌安卓 为了达到商业应用,必须移除被GNU GPL授权证所约束的部份,例如谷歌安卓将驱动程序移到 userspace,使得Linux driver 与 Linux kernel彻底分开。bionic/libc/kernel/ 并非标准的kernel header files。谷歌安卓 的 kernel header 是利用工具由 Linux kernel header 所产生的,这样做是为了保留常数、数据结构与宏。

目前谷歌安卓 的 Linux kernel控制包括安全(Security),存储器管理(Memory Management),程序管理(Process Management),网络堆栈(Network Stack),驱动程序模型(Driver Model)等。下载谷歌安卓源码之前,先要安装其构建工具 Repo来初始化源码。Repo 是 谷歌安卓 用来辅助Git工作的一个工具。

安全权限机制

谷歌安卓本身是一个权限分立的操作系统。在这类操作系统中,每个应用都以唯一的一个系统识别身份运行(Linux用户ID与群组ID)。系统的各部分也分别使用各自独立的识别方式。Linux就是这样将应用与应用,应用与系统隔离开。

系统更多的安全功能通过权限机制提供。权限可以限制某个特定进程的特定操作,也可以限制每个URI权限对特定数据段的访问。

谷歌安卓安全架构的核心设计思想是,在默认设置下,所有应用都没有权限对其他应用、系统或用户进行较大影响的操作。这其中包括读写用户隐私数据(联系人或电子邮件),读写其他应用文件,访问网络或阻止设备待机等。

安装应用时,在检查程序签名提及的权限,且经过用户确认后,软件包安装器会给予应用权限。从用户角度看,一款谷歌安卓应用通常会要求如下的权限:

拨打电话、发送短信或彩信、修改/删除SD卡上的内容、读取联系人的信息、读取日程信的息,写入日程数据、读取电话状态或识别码、精确的(基于GPS)地理位置、模糊的(基于网络获取)地理位置、创建蓝牙连接、对互联网的完全访问、查看网络状态,查看WiFi状态、避免手机待机、修改系统全局设置、读取同步设定、开机自启动、重启其他应用、终止运行中的应用、设定偏好应用、震动控制、拍摄图片等。

一款应用应该根据自身提供的功能,要求合理的权限。用户也可以分析一款应用所需权限,从而简单判定这款应用是否安全。如一款应用是不带广告的单机版,也没有任何附加的内容需要下载,那么它要求访问网络的权限就比较可疑。#p#

组件

技术内容:本系统主要由四个部分组成,即谷歌安卓四大组件,分别是:活动(Activity): 用于表现功能。服务(Service): 相当于后台运行的Activity。广播接收器(BroadcastReceiver):用于接收广播。内容提供商(Content Provider): 支持在多个应用中存储和读取数据,相当于数据库。

1 Activity

谷歌安卓 中,Activity 是所有程序的根本,所有程序的流程都运行在Activity 之中,Activity可以算是开发者遇到的最频繁,也是谷歌安卓 当中最基本的模块之一。在谷歌安卓的程序当中,Activity 一般代表手机屏幕的一屏。如果把手机比作一个浏览器,那么Acitivity就相当于一个网页。在Activity 当中可以添加一些Button、Check box 等控件。可以看到Activity 概念和网页的概念相当类似。

一般一个谷歌安卓 应用是由多个Activity 组成的。这多个Activity 之间可以进行相互跳转,例如,按下一个Button 按钮后,可能会跳转到其他的Activity。和网页跳转稍微有些不一样的是,Activity 之间的跳转有可能返回值,例如,从Activity A 跳转到Activity B,那么当Activity B 运行结束的时候,有可能会给Activity A 一个返回值。这样做在很多时候是相当方便的。

当打开一个新的屏幕时,之前一个屏幕会被置为暂停状态,并且压入历史堆栈中。用户可以通过回退操作返回到以前打开过的屏幕。我们可以选择性的移除一些没有必要保留的屏幕,因为谷歌安卓 会把每个应用的开始到当前的每一个屏幕保存在堆栈中。Activity 是由谷歌安卓 系统进行维护的,它也有自己的生命周期,即它的一个产生、运行、销毁的一个周期,对于Activity,关键是其生命周期的把握,其次就是状态的保存和恢复(onSaveInstanceState onRestoreInstanceState),以及Activity 之间的跳转和数据传输(intent)。

2 Service

Service 是谷歌安卓 系统中的一种组件,它跟Activity 的级别差不多,但是他不能自己运行,只能后台运行,并且可以和其他组件进行交互。Service 是没有界面的长生命周期的代码。Service 是一种程序,它可以运行很长时间,但是它却没有用户界面。这么说有点枯燥,我们来看个例子。打开一个音乐播放器的程序,这个时候若想上网了,那么,我们打开谷歌安卓 浏览器,这个时候虽然我们已经进入了浏览器这个程序,但是,歌曲播放并没有停止,而是在后台继续一首接着一首的播放。其实这个播放就是由播放音乐的Service进行控制。当然这个播放音乐的Service也可以停止,例如,当播放列表里边的歌曲都结束,或者用户按下了停止音乐播放的快捷键等。service 可以在和多场合的应用中使用,比如播放多媒体的时候用户启动了其他Activity这个时候程序要在后台继续播放,比如检测SD 卡上文件的变化,再或者在后台记录你地理信息位置的改变等等,总之服务嘛,总是藏在后头的。开启service有两种方式:

(1) Context.startService():Service会经历onCreate -> onStart(如果Service还没有运行,则谷歌安卓先调用onCreate()然后调用onStart();如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次 );stopService的时候直接onDestroy,如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。 注意,多次调用Context.startservice()不会嵌套(即使会有相应的onStart()方法被调用),所以无论同一个服务被启动了多少次,一旦调用Context.stopService()或者stopSelf(),他都会被停止。补充说明:传递给startService()的Intent对象会传递给onStart()方法。调用顺序为:onCreate --> onStart(可多次调用) --> onDestroy。

(2) Context.bindService():Service会经历onCreate() -> onBind(),onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。这个时候把调用者(Context,例如Activity)会和Service绑定在一起,Context退出了,Srevice就会调用onUnbind -> onDestroyed相应退出,所谓绑定在一起就共存亡了 。

3 BroadcastReceiver

在谷歌安卓 中,Broadcast 是一种广泛运用的在应用程序之间传输信息的机制。而BroadcastReceiver 是对发送出来的Broadcast进行过滤接受并响应的一类组件。可以使用BroadcastReceiver 来让应用对一个外部的事件做出响应。这是非常有意思的,例如,当电话呼入这个外部事件到来的时候,可以利用BroadcastReceiver 进行处理。例如,当下载一个程序成功完成的时候,仍然可以利用BroadcastReceiver 进行处理。BroadcastReceiver不能生成UI,也就是说对于用户来说不是透明的,用户是看不到的。BroadcastReceiver通过NotificationManager 来通知用户这些事情发生了。BroadcastReceiver 既可以在谷歌安卓Manifest.xml 中注册,也可以在运行时的代码中使用Context.registerReceiver()进行注册。只要是注册了,当事件来临的时候,即使程序没有启动,系统也在需要的时候启动程序。各种应用还可以通过使用Context.sendBroadcast () 将它们自己的intent broadcasts广播给其他应用程序。注册BroadcastReceiver有两种方式:

(1)在谷歌安卓Manifest.xml进行注册

 

 

这种方法有一个特点即使你的应用程序已经关闭了,但这个BroadcastReceiver依然会接受广播出来的对象,也就是说无论你这个应用程序时开还是关都属于活动状态都可以接受到广播的事件

(2)在代码中注册广播

//实例化广播接收器对象

BroadcastReceiver bcr = new BroadcastReceiver(){

public void onReceive(Context context, Intent intent) {

Log.d("test", "^-^, Have received Massage!");

}

};

IntentFilter filter=new IntentFilter();

filter.addAction(“XXX”);

this.registerReceiver(bcr, filter);

第一种俗称静态注册,第二种俗称动态注册,这两种注册BroadcastReceiver的区别:

动态注册较静态注册灵活。实验证明:当静态注册一个BroadcastReceiver时,不论应用程序是启动与否。都可以接受对应的广播。

动态注册的时候,如果不执行unregisterReceiver();方法取消注册,跟静态是一样的。但是如果执行该方法,当执行过以后,就不能接受广播了。

4 Content Provider

Content Provider,听着就和数据相关,没错,这就是谷歌安卓提供的第三方应用数据的访问方案。在谷歌安卓中,对数据的保护是很严密的,除了放在SD卡中的数据,一个应用所持有的数据库、文件、等等内容,都是不允许其他直接访问的,但有时候,沟通是必要的,不仅对第三方很重要,对应用自己也很重要。

Andorid当然不会真的把每个应用都做成一座孤岛,它为所有应用都准备了一扇窗,这就是Content Provider。应用想对外提供的数据,可以通过派生ContentProvider类, 封装成一枚Content Provider,每个Content Provider都用一个uri作为独立的标识,形如:content://com.xxxxx。所有东西看着像REST的样子,但实际上,它比REST 更为灵活。和REST类似,uri也可以有两种类型,一种是带id的,另一种是列表的,但实现者不需要按照这个模式来做,给你id的uri你也可以返回列表类型的数据,只要调用者明白,就无妨,不用苛求所谓的REST。

另外,Content Provider不和REST一样只有uri可用,还可以接受Projection,Selection,OrderBy等参数,这样,就可以像数据库那样进行投影,选择和排序。查询到的结果,以Cursor(参见:reference/android/database/Cursor.html )的形式进行返回,调用者可以移动Cursor来访问各列的数据。

Content Provider屏蔽了内部数据的存储细节,向外提供了上述统一的接口模型,这样的抽象层次,大大简化了上层应用的书写,也对数据的整合提供了更方便的途径。Content Provider内部,常用数据库来实现,谷歌安卓提供了强大的Sqlite支持,但很多时候,你也可以封装文件或其他混合的数据。

在谷歌安卓中,ContentResolver是用来发起Content Provider的定位和访问的。不过它仅提供了同步访问的Content Provider的接口。但通常,Content Provider需要访问的可能是数据库等大数据源,效率上不足够快,会导致调用线程的拥塞。因此谷歌安卓提供了一个AsyncQueryHandler(参见:reference/android/content/AsyncQueryHandler.html),帮助进行异步访问Content Provider。

在各大组件中,Service和Content Provider都是那种需要持续访问的。Service如果是一个耗时的场景,往往会提供异步访问的接口,而Content Provider不论效率如何,都提供的是约定的同步访问接口。我想这遵循的就是场景导向设计的原则,因为Content Provider仅是提供数据访问的,它不能确信具体的使用场景如何,会怎样使用它的数据;而相比之下,Service包含的逻辑更复杂更完整,可以抉择大部分时候使用某接口的场景,从而确定最贴切的接口是同步还是异步,简化了上层调用的逻辑。

责任编辑:佚名 来源: 互联网整理
相关推荐

2022-08-02 08:01:09

开发插件Chrome前端技术

2011-07-25 16:21:22

Sencha touc

2012-03-26 09:44:32

安卓开发配置Eclipse

2011-09-22 14:39:17

API

2009-06-24 16:30:21

JSF组件模型

2011-06-09 18:24:36

QT Wince

2023-05-15 18:44:07

前端开发

2012-03-28 09:40:55

安卓开发入门教程视频

2021-08-09 09:47:34

Blazor 路由开发

2012-05-18 10:08:56

TitaniumAndroid

2011-04-18 11:00:34

使用音频BlackBerry

2011-12-29 10:48:49

移动Web

2021-06-21 15:21:52

鸿蒙HarmonyOS应用开发

2010-06-13 09:27:56

Widget开发

2015-11-12 16:14:52

Python开发实践

2015-12-16 10:30:18

前端开发指南

2019-10-31 08:00:00

机器学习人工智能AI

2012-03-28 10:37:55

谷歌安卓开发工具AppInventor

2020-11-17 08:43:20

ElasticSear

2011-12-05 15:44:45

Knockout
点赞
收藏

51CTO技术栈公众号