life02

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  197 随笔 :: 3 文章 :: 37 评论 :: 0 Trackbacks

#

     摘要:   阅读全文
posted @ 2011-12-15 22:28 life02 阅读(392) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2011-12-15 22:25 life02 阅读(450) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2011-12-15 22:13 life02 阅读(182) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2011-12-13 00:33 life02 阅读(392) | 评论 (0)编辑 收藏

Android核心分析
 
 

Android 核心分析 之七------Service深入分析

上一章我们分析了Android IPC架构,知道了Android服务构建的一些基本理念和原理,本章我们将深入分析Android的服务。Android体系架构中三种意义上服务:

Native服务

Android服务

Init空间的服务,主要是属性设置,这个IPC是利用Socket来完成的,这个我将在另外一章来讨论。

Navite服务,实际上就是指完全在C++空间完成的服务,主要是指系统一开始初始化,通过Init.rc脚本起来的服务,例如Service Manger service,Zygote service,Media service , ril_demon service等。

Android服务是指在JVM空间完成的服务,虽然也要使用Navite上的框架,但是服务主体存在于Android空间。Android是二阶段初始(Init2)初始化时建立的服务。

1 Service本质结构

我们还是从Service的根本意义分析入手,服务的本质就是响应客户端请求。要提供服务,就必须建立接收请求,处理请求,应答客服端的框架。我想在Android Service设计者也会无时不刻把这个服务本质框图挂在脑海中。从程序的角度,服务一定要存在一个闭合循环框架和请求处理框架

分析清楚服务框就必须弄清楚以下的机制及其构成。

(1)闭合循环结构放置在哪里?

(2)处理请求是如何分发和管理?

(3)处理框架是如何建立的?

(4)概念框架是如何建立的?

2 Service基本框架分析

Android设计中,Native Service和Android Service采用了同一个闭合循环框架。这个闭合循环框架放置在Native的C++空间中,,ProcessState@ProcessState.cpp 和IPCThreadState@IPCThreadState.cpp两个类完成了全部工作。

在服务框架中,ProcessState是公用的部分,这个公用部分最主要的框架就是闭合循环框架和接收到从Binder来的请求后的处理框架。我们将服务框架用ProcessSate来表示,简言之:

(1) addservice

(2) 建立闭合循环处理框架。

int main(int argc, char** argv)

{

sp<ProcessState> proc(ProcessState::self());

addService(String16("xxx0"), new xxx0Service());

addService(String16("xxx1"), new xxx1Service());

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();//闭合循环框架

}

2.1 Native Service

Native Service是在系统Init阶段通过Init.rc脚本建立的服务。

首先来看看一个例子mediaserver@main_mediaserver.cpp的建立过程。

int main(int argc, char** argv)

{

sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm = defaultServiceManager();

LOGI("ServiceManager: %p", sm.get());

AudioFlinger::instantiate();

MediaPlayerService::instantiate();

CameraService::instantiate();

AudioPolicyService::instantiate();

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

}

我们将代码向下展开了一层,更能看到事物的本质。

int main(int argc, char** argv)

{

sp<ProcessState> proc(ProcessState::self());

sp<IServiceManager> sm = defaultServiceManager();

defaultServiceManager()->addService(String16("media.audio_flinger"), new AudioFlinger());

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

}

(1)服务进程建立了ProcessState对象,并将给对象登记在进程的上下文中。

(2)建立一个新AudioFlinger对象,并将对象登记Service Manager Service中。

(3)开始就收请求,处理请求,应答这个循环闭合框架。

2.2 Android Service

Androids service是系统二阶段(Init2)初始化时建立的服务。

Android的所有服务循环框架都是建立SystemServer@(SystemServer.java)上。在SystemServer.java中看不到循环结构,只是可以看到建立了init2的实现函数,建立了一大堆服务,并AddService到service Manager。

main() @ com/android/server/SystemServer

{

init1();

}

Init1()是在Native空间实现的(com_andoird_server_systemServer.cpp)。我们一看这个函数就知道了,原来这个闭合循环处理框架在这里:

init1->system_init() @System_init.cpp

在system_init()我们看到了这个久违的循环闭合管理框架。

{

Call "com/android/server/SystemServer", "init2"

…..

ProcessState::self()->startThreadPool();

IPCThreadState::self()->joinThreadPool();

}

Init2()@SystemServer.java中建立了Android中所有要用到的服务:

Entropy Service

Power Manager

Activity Manager

Telephony Registry

Package Manager

Account Manager

Content Manager

System Content Providers

Battery Service

Hardware Service

Alarm Manager

Init Watchdog

Sensor Service

Window Manager

Bluetooth Service

statusbar

Clipboard Service

Input Method Service

NetStat Service

Connectivity Service

Accessibility Manager

Notification Manager

Mount Service

Device Storage Monitor

Location Manager

Search Service

Checkin Service

Wallpaper Service

Audio Service

Headset Observer

Backup Service

AppWidget Service

3 ProcessState和IPCThreadState

从宏观来讲,PocessState及其IPCThreadState处于IPC与内核打交道包装层。前面的章节已经提到,下面我将更详细的分析。有关IPC的c++空间的实现都是从ProcessState这个对象完成的。

我们可以得出如下的结论:不管JVM的Binder做了多么复杂的操作,最终还是需要利用ProcessState 这个c++空间的对象把数据传递给Binder Driver,接收数据也是通过ProcessState这个对象完成,ProcessState是所有Binder IPC必经的通道。

ProcessState放置在全局变量gProcess中,每个进程只有一个ProcessState对象,负责打开Binder设备驱动,建立线程池等。而IPCThreadState每个线程有一个,IPCThreadState实例登记在Linux线程程的上下文附属数据中,主要负责Binder数据读取,写入和请求处理框架。IPCThreadSate在构造的时候,获取进程的ProcessSate并记录在自己的成员变量mProcess中,通过mProcess可以获取到Binder的句柄。

3.1 ProcessState的生命周期

既然ProcessState是Binder通讯的基础,那么Process必须在Binder通讯之前建立。客户端,服务端都必须建立。由于现在重点讨论服务端,所以重心放置在服务端。在Android体系中有c++空间的服务,JVM空间的服务,这两类服务在本质上相同的,只是形式上不同,由于他们都是建立在ProcessState这个基础上,所以在形式上不同就仅仅表现在对OnTransact的回调处理的不同。

Native Service

我们直接可以看到使用sp<ProcessState> proc(ProcessState::self()),建立建立ProcessState,一旦调用ProcessState就建立了,并且这个self将ProcessSate登记在全局变量中。

Android Service

建立Android Service服务system_init @System_init.cpp中我们可以看到相同的结构。有一点不同的是所有的Android Service都运行在一个进程中:systemsever进程。

3.2 Binder Driver包装 @IPCThreadState

ProcessSate构造的时候,使用open_binder打开/driver/binder,并将句柄记录在mDriverFD,在ProcessState中并不使用这个句柄,真正使用这个Binder设备句柄的是IPCThreadState,所有关于Binder的操作放置在IPCThreadState中:

(1)读取/写入:talkWithDriver()@IPCThreadState对ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)进行包装。

(2)请求处理:executeCommand(...)@ IPCThreadState

(3)循环结构:joinThreadPool()

joinThreadPool()

{

While(1){

talkWithDriver(...)

...

executeCommand(...)

}

}


posted @ 2011-12-08 11:38 life02 阅读(358) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2011-12-08 11:37 life02 阅读(396) | 评论 (0)编辑 收藏

     摘要: Android软件开发之获取通讯录联系人信息(十二)http://www.uml.org.cn/mobiledev/201110121.asp   发布于2011-10-12   图中选中的数据库 contacts2.db就是系统储存联系人的数据库,我们将它打开看看里面储存了些什么东东? 打开contacts.db后...  阅读全文
posted @ 2011-12-08 11:30 life02 阅读(2215) | 评论 (0)编辑 收藏

     摘要:   阅读全文
posted @ 2011-12-07 23:27 life02 阅读(214) | 评论 (0)编辑 收藏

http://blog.csdn.net/louiswangbing/article/details/6607612

Intent妙用之编写自己的android主界面

众所周知,android的主界面名为 laucher2,功能强大,会在android启动之后运行,也是所有其他应用程序的入口程序。那么,如何让自己的应用程序取代laucher2的位 置,成为android系统的主界面呢?其实说出来很简单,接下来,我就来为大家揭开这其中的神秘面纱。

首先,我们来看看一个普通的应用程序的intent声明:

  1. <intent-filter>  
  2.              <action android:name="android.intent.action.MAIN" />  
  3.              <category android:name="android.intent.category.LAUNCHER" />  
  4.          </intent-filter>  
是不是看着很眼熟呢?没错了,这段代码是在AndroidManifest.xml中相应activity的intent声明,相信大家目前缩写的应用程序的intent声明无一例外都是这样的吧。可能很多人都会对着两行代码有下面的理解:

第二行<action android:name="android.intent.action.MAIN" />表示这个activity是当前应用程序的主activity,而第二行表示当前activity在lancher中加载。

这么理解的却是没错,但事实上,有更加简单的理解方式。这里请容许我先卖个关子。我们继续往下看。

既然是想让我们自己的应用程序取代laucher的位置,那么我们就来看一下lancher的intent声明是怎么样的吧:

  1. <intent-filter>  
  2.         <action android:name="android.intent.action.MAIN" />  
  3.         <category android:name="android.intent.category.HOME"/>  
  4.         <category android:name="android.intent.category.DEFAULT" />  
  5.         <category android:name="android.intent.category.MONKEY" />  
  6.     </intent-filter> 
当 然,想要看到这段代码,你必须要有laucher的源代码。(关于android源代码的问题,前面的文章已经提到过很多次了,有源代码真的是件很好的事 情,不管是对应用程序开发者来说还是对底层开发者来说亦或是对android爱好者来说,都会受益匪浅的,所以这里再次建议大家不要仅仅局限于 android sdk和avd的使用来进行应用程序的开发,不管你有没有时间,下份源代码总是没有坏处的。)

大家看出这两个intent声明之间的差别了吗?没错,当出现  <category android:name="android.intent.category.HOME"/>  的时候,我们的应用程序就会变成跟lancher具有相同功能的(当然,我指的仅仅是主界面,laucher的功能是在是太强大了),成为 android系统的主界面,并且,当我们按下Home键的时候,会出现一个选择界面,是不是发现你的应用程序和laucher同时出现在了选择框中呢? 如果是,那么恭喜你,从功能上来说,你已经实现了。如果没有看到,请email我louiswangbing@gmail.com。

但是,所谓一山不容二虎,同时有两个主界面存在当然不是我们想要的。

如 果你有android源代码的话,你甚至可以把laucher删掉,直接将你自己的应用程序编译到android系统中,这样,系统启动的时候就会直接运 行你的应用程序,而你的应用程序就会堂而皇之地鸠占鹊巢,顺理成章的成为系统的主界面,并且当你按下Home键的时候,就会跳到你的应用程序的主 activity了!!

如果你只是一个功能上的追求者,那么看到这里你就可以关掉这个页面去试试上面的功能了。

如果你是一个好奇心比较强的人,那么请跟着我继续往下看。

刚才我说过,intent声明的理解问题。事实上,你可以有更好的理解方式,当然,这要建立在你对android系统的启动进程有一定的了解的基础上。

简 单来说,intent其实就是一个条件过滤器,activity的intent声明的每一条都可以作为一个过滤条件,条目越多,过滤条件也就越强,定位起 来也就越容易。相信这个原理学过数据库的朋友理解起来更加容易。你可以将整个android系统中所有的activity都集中起来当成是一个数据库,而 intent本身就是一条select语句,其中每一项声明都是一项过滤条件,而过滤之后剩下的,就是将要被调用的activity。当过滤条件足够强大 或者过滤条件比较特殊的时候,最后剩下的只有一个activity,那么系统会毫不犹豫地启动它;当过滤条件不足导致过滤之后还剩下比较多的 activity的时候,系统会将满足这些条件的所有的activity用一个listview列出来让你选择。

相信原理大家都已经很清楚了,那么上面所述的这个功能就很好理解了。没错,android在启动的时候会有一个PackageManager选择系统中满足过滤条件:

  1. <action android:name="android.intent.action.MAIN" />  
  2.         <category android:name="android.intent.category.HOME"/>  
  3.         <category android:name="android.intent.category.DEFAULT" />  
  4.         <category android:name="android.intent.category.MONKEY" />  
的 activity作为系统启动的第一个activity,也就是主界面,任何一个满足这个过滤条件的activity都将进入候选名单,如果候选名单中仅 有一人,那么很荣幸,不战而胜,你就是系统的主界面了;如果候选名单中有多个人(比如刚才说的有laucher和你自己的应用程序),那么就进入残酷的” 民意选举“,也就是用户自己的选择,你选谁系统就会启动谁。但和民意选举不同的是,选举出来的结果通常会有一定的任期,而这个主界面的选举任期非常的短, 每当你按下一次Home键或者重启一下系统,系统就会重新安排一次”民意选举“。如果想要永远的成为主界面,那么唯一的办法就是--没错,虽然很残酷,但 不得不说--就是,干掉它......或者和谐一点,你可以让它活着,但是也必须将它贬为庶民或者是将其发配边疆,具体的实施手段就是--改掉它的 intent声明,使其不满足主界面的这个过滤条件。

在 整个intent妙用章节中,这一章算是比较特殊的,因为虽然所有的章节运用的原理基本相通,也就是我上面说到的原理,但是后续章节的intent过滤条 件都是可以由用户自己定义、手动修改的,而唯独只有这个是不能改的,你只能决定去适应或者不适应这个过滤条件,而不能去改变这个过滤条件,就像你只能去适 应这个社会,却很难改变它--或许不是不能,而是暂时还能找到途径......

有时候真的,生活跟计算机,居然有如此之多的相似之处......


posted @ 2011-12-07 23:26 life02 阅读(295) | 评论 (0)编辑 收藏


http://blog.csdn.net/louiswangbing/article/details/6610936

Android开发组件——Intent

Intent提供了一种通用的消息系统,允许你的应用程序与其它的应用程序间传递Intent来执行动作和产生事件。通过使用Intent可以激活Android应用的三个核心组件:活动、服务和广播接收器。

Intent 的意思是意图,也就是说App通过Intent向android表达自己的意图即想干什么,想启动另一个Activity或者去调用其它的App等 等;Intentfilter反应了App对意图的响应能力,比如书上的例子拨号程序,在自己的App中声明一个Intentfilter对这个动作意图 进行相应,这样当我们按下拨号键时,android就会在所用的Intentfilter中找到合适的App来满足。

¥  Intent的分类

Ø  显示意图

调用Intent.setComponent()或Intent.setClass()方法明确指定了组件名的Intent为显示意图,明确指定了Intent应该传递到哪个组件。

Ø  隐式意图

没有明确指定组件名的Intent为隐式意图。Android系统会根据隐式意图中设置的动作、类别、数据找到最适合的组件来处理这个意图

¥  Intent究竟是什么

我 们可以将Intent看成是Activity通信的标准的。比如Intent中的内容告诉了系统激发Intent的Activity需要什么服务,而服务 者Activity应该满足的条件。然后就是Android系统的事了,它负责找出符合条件的Activity服务者,并将Intent给 Activity服务者,然后这个Activity根据Intent中剩余的信息做出相应的操作。由上面可知,Intent包含两部分信息:

Ø  Activity服务者的信息,这个是给Android用来找到合适Activity的。

Ø  Activity服务者要做什么操作的信息,这个是给Activity服务者用的。

¥  Intent

Android 中提供了Intent机制来协助应用间的交互与通讯,Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述,Android则根据此 Intent的描述,负责找到对应的组件,将Intent传递给调用的组件,并完成组件的调用。Intent不仅可用于应用程序之间,也可用于应用程序内 部的Activity/Service之间的交互。因此,Intent在这里起着一个媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调 用者之间的解耦。

¥  Intent的属性

Ø  Action

表示要执行的动作,当然也可以自定义动作,并可定义相应的Activity

来处理我们的自定义动作。

Ø  Data

也就是执行动作要操作的数据。Android中采用指向数据的一个URI

来表示。如在联系人应用中,一个指向某联系人的URI可能为:content://contacts/1。对于不同的动作,其URI数据的类型是不同的(可以设置type属性指定特定类型数据),如ACTION_EDIT指定Data为文件URI,打电话为tel:URI,访问网络为http:URI,而由content provider提供的数据则为content:URIs。

 如果动作字段是ACTION_EDIT,数据字段包含将显示用于编辑的文

档的URI;如果动作时ACTION_CALL。数据字段将是一个tel:URI和将拨  打的号码;如果动作是ACTION_VIEW,数据字段是一个http:URI,接收活动将被调用去下载和显示URI指向的数据。

Ø  Type

数据类型,显示指定Intent的数据类型(MIME)。一般Intent的数据

类型能够根据数据本身进行判断,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。

Ø  Category

被执行动作的附加信息。例如LAUNCHER_CATEGORY表示intent的接

受 者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作 可以在同一数据上执行。Alternative表明,这个Activity可以变成OptionMenu,供其他Activity直接调用。

Ø  Component

指定Intent的目标组件的类名称。通常Android会根据Intent中包含

的 其它属性的信息,比如action、data/type、category进行查找,最终找到一个与之匹配的目标组件。但是,如果component这个 属性有指定的话,将直接使用它指定的组件,而不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。

Ø  Extra

是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,

比如,如果要执行“发送电子邮件”这个动作,可以将电子邮件的标题、正文等保存在extras里,传给电子邮件发送组件。

Android需要解析的是那些隐式Intent,通过解析,将Intent映射给可以

处理此Intent的Activity、IntentReceiver或Service。Intent解析机制主要是通

过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,

最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action、

type、category这三个属性来进行判断,判断方法如下:

@  如果Intent指定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则就不能匹配。

@  如果Intent没有提供type,系统将从data中得到数据类型。和action一样,目标组件的数据类型列表中必须包含Intent的数据类型,否则不能匹配。

@  如果Intent中的数据不是content:类型的URI,而且Intent也没有明确指定它的type,将根据Intent中数据的scheme(比 如http:或者mailto:)进行匹配。同上,Intent的scheme必须出现在目标组件的scheme列表中。

@  如果Intent指定了一个或多个category,这些类别必须全部出现在组件的类别列表中。比如Intent中包含了两个类别:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析得到的目标组件必须至少包含这两个类别。

当匹配一个intent到一个能够处理数据的组件,通常知道数据的类型(它

的MIME 类型)和它的URI很重要。例如,一个组件能够显示图像数据,不应该被调用去播放一个音频文件。

 在许多情况下,数据类型能够从URI中推测,特别是content:URIs,它表

示 位于设备上的数据且被内容提供者(content provider)控制。但是类型也能够显示地设置,setData()方法指定数据的URI,setType()指定MIME类 型,setDataAndType()指定数据的URI和MIME类型。通过getData()读取URI,getType()读取类型。

¥  Intent过滤器

活动、服务、广播接收者为了告知系统能够处理哪些隐式Intent,它们

可 以有一个或多个intent过滤器。每个过滤器描述组件的一种能力,即乐意接收的一组Intent。实际上,它筛掉不想要的Intents,也仅仅是不想 要的隐式Intents。一个显示Intent总是能够传递到它的目标组件,不管它包含什么;不考虑过滤器。但是一个隐式Intent,仅当它能够通过组 件的过滤器之一才能够传递给它。

一个组件能够做的每一工作有独立的过滤器,例如,记事本中的NoteEditer活动有两个过滤器,一个是启动一个指定的记录,用户可以查看和编辑;另一个是启动一个新的、空的记录,用户能够填充并保存。

一 个intent过滤器是一个IntentFilter类的实例。因为Android系统在启动一个组件之前必须知道它的能力,但是intent过滤器通常 不在java代码中设置,而是在应用程序的清单文件(AndroidManifest.xml)中设置。但是有一个例外,广播接收者的过滤器通过调用 Context.registerReceiver()动态地注册,它直接创建一个IntentFilter对象。

一 个过滤器有对应于Intent对象的动作、数据、种类的字段。过滤器要检测隐式Intent的所有这三个字段,其中任何一个失败,Android系统都不 会传递Intent给组件。然而,因为一个组件可以有多个Intent过滤器,一个Intent通不过组件的过滤器检测,其它的过滤器可能通过检测。

一个过滤器必须至少包含一个<action>子元素,否则它将阻塞所有的Intents。

要通过检测,Intent对象中指定的动作必须匹配过滤器的动作列表中的一个。如果对象或过滤器没有指定一个动作,结果将如下:

ž   如果过滤器没有指定动作,没有一个Intent将匹配,所有的Intent将检测失败,即没有intent能够通过过滤器。

ž   如果Intent对象没有指定动作,将自动通过检查(只要过滤器至少有一个过滤器,否则就是上面的情况了)

对于一个Intent要通过种类检测,Intent对象中的每个种类必须匹配过

滤器中的一个。即过滤器能够列出额外的种类,但是Intent对象中的种类都必须能够在过滤器中找到,只有一个种类在过滤器列表中没有,就算种类检测失败!

        因此原则上如果一个Intent对象中没有种类(即种类字段为空)应该总

是 通过种类测试,而不管过滤器中有什么种类。但是有个例外,Android对待所有传递给Context.startActivity()的隐式 Intent好像它们至少包含”android.intent.category.DEFAULT”(对应CATEGORY_DEFAULT常量)。因 此,活动想要接收隐式Intent必须要在Intent过滤器中包含”android.intent.category.DEFAULT”。

      Intents对照着Intent过滤器匹配,不仅去发现一个目标组件去激活,而且

去 发现设备上的组件的其他信息。例如,Android系统填充应用程序启动列表,最高层屏幕显示用户能够启动的应用程序:是通过查找所有的包含指定 了”android.intent.action.MAIN”的动作和”android.intent.category.LAUNCHER” 种         类的过滤器的活动,然后在活动列表中显示这些活动的图标和标签。类似的,   它通过查找”android.intent.category.HOME”过滤器的活动发掘主菜单。

¥  Intent示例

要实现两个Activity的跳转,我们可以将要跳转的Activity类名绑定到

Intent对象中,然后通过startActivity方法激活Intent对象中所指定的Activity,关键代码如下:


posted @ 2011-12-07 23:25 life02 阅读(316) | 评论 (0)编辑 收藏

仅列出标题
共20页: First 8 9 10 11 12 13 14 15 16 Last