在manifest文件里->activity 添加
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*">
</intent-filter>
这样就把当前程序注册为 可以打开/查看所有类型的文件. 或者要查看jpeg, mimeType要改为: image/jpeg
当在文件管理器里点击任何文件, 系统都会试图去执行你的程序.
转自 http://chaozhong84.spaces.live.com/blog/cns!FC149E9A3FC0182B!297.trak
【Android】【转】Android Log Analysis
---------------------------------------------------
本文原创,转载请注明出处,如有错误之处欢迎指出
---------------------------------------------------
Get Log from Android System
adb bugreport > bugreport.txt
copy bugreport to the current directory.
bugreport里面包含了各种log信息,大部分log也可以通过直接运行相关的程序来直接获得.
步骤如下:
1.adb shell 2.进入相关工具程式的目录 3.执行相关程式 4.得到相关信息
下面以输出进程信息为例 1.adb shell 2.输入ps -P 3.可以看到相关进程信息
Log Archive Analysis
1.bugreport
bugreport记录android启动过程的log,以及启动后的系统状态,包括进程列表,内存信息,VM信息等等到.
2.bugreport结构分析
(1)dumpstate
MEMORY INFO
获取该log:读取文件/proc/meminfo
系统内存使用状态
CPU INFO
获取该log:执行/system/bin/top -n 1 -d 1 -m 30 -t
系统CPU使用状态
PROCRANK
获取该log:执行/system/bin/procrank
执行/system/xbin/procrank后输出的结果,查看一些内存使用状态
VIRTUAL MEMORY STATS
获取该log:读取文件/proc/vmstat
虚拟内存分配情况
vmalloc申请的内存则位于vmalloc_start~vmalloc_end之间,与物理地址没有简单的转换关系,虽然在逻辑上它们也是连续的,但是在物理上它们不要求连续。
VMALLOC INFO
获取该log:读取文件/proc/vmallocinfo
虚拟内存分配情况
SLAB INFO
获取该log:读取文件/proc/slabinfo
SLAB是一种内存分配器.这里输出该分配器的一些信息
ZONEINFO
获取该log:读取文件/proc/zoneinfo
zone info
SYSTEM LOG(需要着重分析)
获取该log:执行/system/bin/logcat -v time -d *:v
会输出在程序中输出的Log,用于分析系统的当前状态
VM TRACES
获取该log:读取文件/data/anr/traces.txt
因为每个程序都是在各自的VM中运行的,这个Log是现实各自VM的一些traces
EVENT LOG TAGS
获取该log:读取文件/etc/event-log-tags
EVENT LOG
获取该log:执行/system/bin/logcat -b events -v time -d *:v
输出一些Event的log
RADIO LOG
获取该log:执行/system/bin/logcat -b radio -v time -d *:v
显示一些无线设备的链接状态,如GSM,PHONE,STK(Satellite Tool Kit)...
NETWORK STATE
获取该log:执行/system/bin/netcfg (得到网络链接状态)
获取该log:读取文件/proc/net/route (得到路由状态)
显示网络链接和路由
SYSTEM PROPERTIES
获取该log:参考代码实现
显示一些系统属性,如Version,Services,network...
KERNEL LOG
获取该log:执行/system/bin/dmesg
显示Android内核输出的Log
KERNEL WAKELOCKS
获取该log:读取文件/proc/wakelocks
内核对一些程式和服务唤醒和休眠的一些记录
KERNEL CPUFREQ
(Linux kernel CPUfreq subsystem) Clock scaling allows you to change the clock speed of the CPUs on the fly.
This is a nice method to save battery power, because the lower the clock speed is, the less power the CPU consumes.
PROCESSES
获取该log:执行ps -P
显示当前进程
PROCESSES AND THREADS
获取该log:执行ps -t -p -P
显示当前进程和线程
LIBRANK
获取该log:执行/system/xbin/librank
剔除不必要的library
BINDER FAILED TRANSACTION LOG
获取该log:读取文件/proc/binder/failed_transaction_log
BINDER TRANSACTION LOG
获取该log:读取文件/proc/binder/transaction_log
BINDER TRANSACTIONS
获取该log:读取文件/proc/binder/transactions
BINDER STATS
获取该log:读取文件/proc/binder/stats
BINDER PROCESS STATE
获取该log:读取文件/proc/binder/proc/*
bind相关的一些状态
FILESYSTEMS
获取该log:执行/system/bin/df
主要文件的一些容量使用状态(cache,sqlite,dev...)
PACKAGE SETTINGS
获取该log:读取文件/data/system/packages.xml
系统中package的一些状态(访问权限,路径...),类似Windows里面的一些lnk文件吧.
PACKAGE UID ERRORS
获取该log:读取文件/data/system/uiderrors.txt
错误信息
KERNEL LAST KMSG LOG
最新kernel message log
LAST RADIO LOG
最新radio log
KERNEL PANIC CONSOLE LOG
KERNEL PANIC THREADS LOG
控制台/线程的一些错误信息log
BACKLIGHTS
获取该log:获取LCD brightness读/sys/class/leds/lcd-backlight/brightness
获取该log:获取Button brightness读/sys/class/leds/button-backlight/brightness
获取该log:获取Keyboard brightness读/sys/class/leds/keyboard-backlight/brightness
获取该log:获取ALS mode读/sys/class/leds/lcd-backlight/als
获取该log:获取LCD driver registers读/sys/class/leds/lcd-backlight/registers
获取相关亮度的一些信息
(2)build.prop
VERSION INFO输出下列信息
当前时间
当前内核版本:可以读取文件(/proc/version)获得
显示当前命令:可以读取文件夹(/proc/cmdline)获得
显示系统build的一些属性:可以读取文件(/system/build.prop)获得
输出系统一些属性
gsm.version.ril-impl
gsm.version.baseband
gsm.imei
gsm.sim.operator.numeric
gsm.operator.alpha
(3)dumpsys
执行/system/bin/dumpsys后可以获得这个log.
经常会发现该log输出不完整,因为代码里面要求该工具最多只执行60ms,可能会导致log无法完全输出来.
可以通过修改时间参数来保证log完全输出.
信息:
Currently running services
DUMP OF SERVICE services-name(running)
Log Code Analysis
Site: ."frameworks"base"cmds"dumpstate"
相关Log程序的代码可以从上面目录获取
Log Analysis Experience
分析步骤
1.查看一些版本信息
确认问题的系统环境
2.查看CPU/MEMORY的使用状况
看是否有内存耗尽,CPU繁忙这样的背景情况出现.
3.分析traces
因为traces是系统出错以后输出的一些线程堆栈信息,可以很快定位到问题出在哪里.
4.分析SYSTEM LOG
系统Log详细输出各种log,可以找出相关log进行逐一分析
实例分析
下面分析我写的一个测试例子,在OnCreate做一个死循环,这样主线程会被锁住,在按下硬件的Back之后会出现ANR的错误.
在traces中发现该程序的堆栈信息如下:
----- pid 20597 at 2010-03-15 01:29:53 -----
Cmd line: com.android.test
DALVIK THREADS:
"main" prio=5 tid=3 TIMED_WAIT
| group="main" sCount=1 dsCount=0 s=N obj=0x2aac6240 self=0xbda8
| sysTid=20597 nice=0 sched=0/0 cgrp=default handle=1877232296
at java.lang.VMThread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:1306)
at java.lang.Thread.sleep(Thread.java:1286)
at android.os.SystemClock.sleep(SystemClock.java:114)
at com.android.test.main.onCreate(main.java:20)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
at android.app.ActivityThread.access$2200(ActivityThread.java:119)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4363)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
"Binder Thread #2" prio=5 tid=11 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c260 self=0x143860
| sysTid=20601 nice=0 sched=0/0 cgrp=default handle=1211376
at dalvik.system.NativeStart.run(Native Method)
"Binder Thread #1" prio=5 tid=9 NATIVE
| group="main" sCount=1 dsCount=0 s=N obj=0x2fb7c1a0 self=0x14c980
| sysTid=20600 nice=0 sched=0/0 cgrp=default handle=1207920
at dalvik.system.NativeStart.run(Native Method)
"Signal Catcher" daemon prio=5 tid=7 RUNNABLE
| group="system" sCount=0 dsCount=0 s=N obj=0x2fb7a1e8 self=0x126cc0
| sysTid=20599 nice=0 sched=0/0 cgrp=default handle=1269048
at dalvik.system.NativeStart.run(Native Method)
"HeapWorker" daemon prio=5 tid=5 VMWAIT
| group="system" sCount=1 dsCount=0 s=N obj=0x2e31daf0 self=0x135c08
| sysTid=20598 nice=0 sched=0/0 cgrp=default handle=1268528
at dalvik.system.NativeStart.run(Native Method)
----- end 20597 -----
该文件的堆栈结构从下往上进行分析
(1)栈底at dalvik.system.NativeStart.run(Native Method)
系统为当前的task(应用程式)启动一个专用的虚拟机
(2) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
Activity Services是在后台负责管理Activity,它此时将测试例子的Activity启动起来了
(3)at com.android.test.main.onCreate(main.java:20)
启动测试程序
(4)栈顶at java.lang.VMThread.sleep(Native Method)
线程被sleep掉了,所以无法响应用户,出现ANR错误.
上面是对一个非常简单的问题的分析.
如果遇到比较复杂的问题还需要详细分析SYSTEM LOG.
1.比如网络异常,要通过SYSTEM LOG里面输出的网络链接信息来判断网络状态
2.数据传输,网络链接等耗时的操作需要分析SYSTEM LOG里面ActivityManager的响应时间
(1) Looper类别用来为一个线程开启一个消息循环。默认情况下Android中新诞生的线程是没有开启消息循环的。(主线程除外,主线程系统会自动为其创建Looper对象,开启消息循环)
Looper对象通过MessageQueue来存放消息和事件。一个线程只能有一个Looper,对应一个MessageQueue。
(2) 通常是通过Handler对象来与Looper交互的。Handler可看做是Looper的一个接口,用来向指定的Looper发送消息及定义处理方法。
默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,在主线程中定义,其是与主线程的Looper绑定。
mainHandler = new Handler() 等价于new Handler(Looper.myLooper()).
Looper.myLooper():Return the Looper object associated with the current thread 获取当前进程的looper对象。
还有一个类似的 Looper.getMainLooper() 用于获取主线程的Looper对象。
(3) 在非主线程中直接new Handler() 会报如下的错误:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
原因是非主线程中默认没有创建Looper对象,需要先调用Looper.prepare()启用Looper。
(4) Looper.loop(); 让Looper开始工作,从消息队列里取消息,处理消息。
注意:写在Looper.loop()之后的代码不会被执行,这个函数内部应该是一个循环,当调用mHandler.getLooper().quit()后,loop才会中止,其后的代码才能得以运行。
(5) 基于以上知识,可实现主线程给子线程(非主线程)发送消息。
把下面例子中的mHandler声明成类成员,在主线程通过mHandler发送消息即可。
(6) Android官方文档中Looper的介绍:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation ofprepare() and loop() to create an initial Handler to communicate with the Looper.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
px (pixels) 像素
dip (device independent pixels) 设备独立像素
sp (scaled pixels - best for text size ) 放大像素,对文本大小最好
pt (points) 点
in (inches) 英寸
mm (millimeters) 毫米
很多网友可能发现在Android的layout文件中layout_width或layout_height有时候可能会指定具体的单位,比如有时候为px、dip或者sp等等。下面android123把常见的单位做下简单的介绍,比如说
px (pixels)像素 -- 一般我们HVGA代表320x480像素,这个用的比较多。
dip或dp (device independent pixels)设备独立像素 -- 这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA cwj推荐使用这个,不依赖像素。
sp (scaled pixels — best for text size)放大像素-- 主要处理字体的大小。
下面的几个是不常用的,大家也知道这里android123就不再过多的赘述。
in (inches)英寸
mm (millimeters)毫米
pt (points)点
px像素如何转为dip设备独立像素
最近有网友问如何将px像素转为dip独立设备像素,由于Android的设备分辨率众多,目前主流的为wvga,而很多老的设备为hvga甚至低 端的qvga,对于兼容性来说使用dip无非是比较方便的,由于他和分辨率无关和屏幕的密度大小有关,所以推荐使用,不过这里android123提示大 家,ophone os的手机对于dip的支持糟糕透了,显示的结果会放大很多,同时黑色的主题会导致常规的黑色文字让用户无法分辨。
px= (int) (dip*density+0.5f) //这里android开发网提示大家很多网友获取density的方法存在问题,从资源中获取的是静态定义的,一般为1.0对于HVGA是正好的,而对于wvga这样的应该从WindowsManager中获取,WVGA为1.5
QVGA HVGA WVGA区别
文章分类:移动开发
QVGA即"Quarter VGA"。顾名思义即VGA的四分之一尺寸,亦即在液晶屏幕(LCD)上输出的分辨率是240×320像素。QVGA支持屏幕旋转,可以开发出相应的程序,以显示旋转90°、180°、270°屏幕位置。由HandEra公司发布。多用于手持/移动设备。 需要说明的是有些媒体把QVGA屏幕当成与TFT和TFD等LCD材质相同的东西是错误的,QVGA屏幕的说法多见与日本的一些手机中,目前采用微软Pocket PC操作系统的智能手机屏幕也大多是320×240像素的QVGA屏幕。 所谓QVGA液晶技术,就是在液晶屏幕上输出的分辨率是240×320的液晶输出方式。这个分辨率其实和屏幕本身的大小并没有关系。比如说,如果2.1英寸液晶显示屏幕可以显示240×320分辨率的图像,就叫做“QVGA 2.1英寸液晶显示屏”;如果3.8英寸液晶显示屏幕可以显示240×320的图像,就叫做“QVGA 3.8英寸液晶显示屏”,以上两种情况虽然具有相同的分辨率,但是由于尺寸的不同实际的视觉效果也不同,一般 HVGA 即VGA(640*480)的一半,分辨率为(480*320),(3:2宽高比) 它是用于各种各样的PDA设备,首先是2002年的索尼Clie PEG - NR70, 来说屏幕小的一个画面自然也会细腻一些。 WVGA 数码产品屏幕材质的一种,VGA的另一种形式,比VGA分辨率高,别名 : Wide VGA, ,其分辩率为800×480象素。是扩大了VGA(640×480)的分辨率。应用于PDA和手机等,因为很多网页的宽度都是800,所以WVGA的屏幕会更加适和于浏览网页,可以说是未来手持设备的分辨率的大趋势
android:padding 属性允许你设置相同的4个方向的间距值,组件的内容在间距内的中间。如果你要四个不同数值的间距值,,可以分别使用 android:paddingLeft,android:paddingRight,android:paddingTop和 android:paddingBottom。间距值是一个具体的数值,如果要5像素,则可以对应填写”5px”.
如 果你应用组件的默认背景(例如,通过android:backgound属性),背景将会同时显示在间距和组件上。为了避免这种情况,用 padding,还不如用margin,这可以只增加空白的空间,并不会撑大组件。你可以通过android:layoout_margin属性来实现。
例如:<com.android.motoswitch.HandleView
style="@style/HotseatButton"
android:id="@+id/all_apps_button"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:src="@drawable/all_apps_button"
switcher:direction="horizontal"
/>
Android核心分析(22)-----Android应用框架之Activity 收藏
3 Activity设计框架
3.1 外特性空间的Activity
我们先来看看,Android应用开发人员接触的外特性空间中的Activity,对于AMS来讲,这个Activity就是客服端的Activity。应用程序员在建立Android应用时,构建Activity的子类就是Andoid外特性空间展现的接口。我们可以从下面的简单的例子描述看看Activity,到底如何建立的。
DemoActivity extend Activity
{
onCreate
onResume
onPause
onStop
}
在Android的外特性空间(SDK)中,Android应用程序员根本不知道进程是什么时候起来的,系统消息是如何传递过来的。这个DemoActivity是如何实例化的呢?并且该Activity是托管在哪个进程的呢?本节的分析将给出答案。
我们从ActivityThread中可以看到在应用进程中的Activity都被放置在mActivities中。
这些ActivityRecord记录了应用进程中,程序员建立的Activity子类的实例,我们称之为外特性空间的Activity。这些Activity类实例是放在应用程序端进行实际交互的Activity,而为了管理这些Activity,AMS内核中还有一个影子Activity,被称为HistoryRecord。
3.2 Activity与HistoryRecord的关系
在整个系统中,Activity实际上有两个实体。一个在应用进程中跟应用程序员打交道的Activity,一个是在AMS的中具有管理功能的History Record。应用进程中的Activity都登记ActivityThread实例中的mActivity数组中,而在AM端,HistroytRecord实例放置在mHistroy栈中。mHistory栈是Android管理Activity的场所,放置在栈顶的就是User看到的处于活动状态的Activity。
Activity与HistrotyRecord的关系图可以表示如下:
Activity的内核实体是依靠在ProcessRecord的成员变量中,通过ProcessRecord我们可以访问到所有的属于该Process的Activity。而在ProcessRecord记录了与应用进程之间的联系:IActivtityThread接口。通过该接口,可以访问到所对应的Activity的方法。在Launch Activity时,AMS将对应的HistoryRecord作为token传递到客服端和客服端的Activity建立联系。在AMS中Activity状态变化时,将通过该联系找到客服端的Activity,从而将消息或者动作传递应用程序面对的接口:xxxActivity。
3.3 Actvity的Launch过程
1)发起请求startActivity(intent)
2)Activity Service Manager接收到请求执行StartActivity函数。
建立:HistoryRecord实例r.
将r 加入到mHistory顶。
(3)通过app.thread.scheduleLaunchActvity( app,r)@ActivityThread.java
(4)在App应用中建立新的ActivityRecord。
(5)建立新的Activity对象并放入到ActivityRecord中。
(6)将ActivityRecord加入到mActivites@ActivityThread
(7)发起Activity.onCreate(..),,该onCreate就是在你的应用程序XXXActivity中的onCreate。
3.4 Activity的Resume
(1)Activity什么时候被Resume
(2)Rusume的过程
通过该过程的研究我们会进一步的了解到AMS与应用进程的交互过程。
在AMS端,满足resume条件都会调用:Resume的核心函数:resumeTopActivityLocked@ActivityManagerService
XXX当前栈顶的HistroyRecord
1)窗口切换:隐藏前一个Activity的窗口,
2)更新LRUList,(LRUList是淘汰应用程序的依据之一)
3) XXX.app.thread.scheduleResumeActivity(XXX,
isNextTransitionForward());
4)completeResumeLocked
setFocusedActivityLocked
mFocusActivity=xxx //此时焦点Actvitiy切换了。
WM.setFocusedApp(xxx,
mWindowManager.executeAppTransition();
mNoAnimActivities.clear();
在应用程序端:
(5)scheduleResumeActivity
handleResumeActivity(IBinder token, boolean clearHide, boolean isForward) {
ActivityRecord r = performResumeActivity(token, clearHide);
ActivityRecord r = mActivities.get(token);
r.activity.performResume()
performResume
整个Resume的过程如下:
Android Application
Android提供给开发程序员的概念空间中Application只是一个松散的表征概念,没有多少实质上的表征。在Android实际空间中看不到实际意义上的应用程序的概念,即使有一个叫Application的类,这个也就是个应用程序上下文状态,是一个极度弱化的概念。Application只是一个空间范畴的概念,Application就是Activity,Service之类的组件上下文描述。Application并不是Android的核心概念,而Activity才是Android的核心概念。
从Android的SDK文档中,我们知道一般情况Android应用程序是由以下四种组件构造而成的:Activity,Broadcast Intent Receiver,服务(Service),内容提供器(Content Provider)。我们可以使用下面的图来表示一下Android的概念空间。这些组件依附于应用程序中,应用程序并不会一开始就建立起来,而是在这些组件建立起来后,需要运行时,才开始建立应用程序对象。
2.1应用进程名称
为什么要从应用进程名称开始?作为内核研究,我们还是回到问题的最本质处:不管Activity,Service等组件如何设计和运行,它要提供服务,就必须要依附在Linux的进程上,建立消息循环,组件才能够真正的运作。Activity实例是如何Hosting在Linux进程上的?这个是我们首先想要弄明白的。
我们在的项目中看到android:process="string"这个定义。
allowClearUserData=["true" | "false"]
android:allowTaskReparenting=["true" | "false"]
android:backupAgent="string"
…
android:label="string resource"
android:manageSpaceActivity="string"
android:name="string"
android:permission="string"
android:persistent=["true" | "false"]
android:process="string"
android:restoreAnyVersion=["true" | "false"]
android:taskAffinity="string"
android:theme="resource or theme" >
. . .
在SDK用已经描述的很清楚到了。
android:process
The name of a process where all components of the application should run. Each component can override this default by setting its own process attribute.
By default, Android creates a process for an application when the first of its components needs to run. All components then run in that process. The name of the default process matches the package name set by the element.
By setting this attribute to a process name that's shared with another application, you can arrange for components of both applications to run in the same process — but only if the two applications also share a user ID and be signed with the same certificate.
为什么要提出这么一个定义?android:process名称。
默认状态下,Activity Manager Service在应用程序的第一个组件需要运行时将会为应用程序建立一个进程,而这个进程的名字就是android:process=”string”所指定,缺省的是应用程序包的名字。该进程一旦建立,后面的该应用的组件都将运行在该进程中,他们绑定的根据就是这个Android:Process指定的名称,因为在他们都在同一个应用程序包里,也就具有了同样的进程名字,于是他们都托管在了同一进程中。组件将通过ClassLoader从Package中获取到应用程序的信息。
在建立Actvitiy时,如果在应用进程端没有应用对象,系统在该过程中利用makeApplication建立一个Application对象,实例化"android.app.Application",建立一个应用程序上下文完成例如资源,package等信息管理。
2.2 ActivityThread运行框架
在分析中,我们可以看到真正对应应用进程的不是Application而是ActivityThread。我们从实际的应用堆栈可以看到:
NaiveStart.main()
ZygoteInit.main
ZygoteInit$MethodAndArgsCall.run
Method.Invoke
method.invokeNative
ActivityThread.main()
Looper.loop()
....
每个应用程序都以ActivityThread.main()为入口进入到消息循环处理。对于一个进程来讲,我们需要这个闭合的处理框架。
ActivitiyThread是应用程序概念空间的重要概念,他建立了应用进程运行的框架,并提供了一个IActivityThread接口作为与Activity Manager Service的通讯接口.通过该接口AMS可以将Activity的状态变化传递到客户端的Activity对象。
2.3 ActivitiyThread的建立
为了叙述的方便我将Actvitiy Manager Service简写成AMS。
在AMS中关于应用程序的概念是ProcessRecord,请求都是从Activity,Service…等开始的,在Activity需要Resume时,此时如果与Activity相关的应用进程没有起来,AM则启动应用进程。
AMS与应用进程的绑定分为两个部分,第一部分就是AM建立应用进程,第二部分就是应用进程Attach到AM,与AM建立通讯通道。
1)创建建立进程:startProcessLocked(processName,Appinfo.uid)。该函数在StartSecificActivityLocked等调用。
(1)建立ProcessRecord对象app,并将该对象添加到mProcessNames中。应用对象在mProcessNames中使用应用名字和uid来标识自己。如果在同一个Package中的Activity,如果都使用默认设置,那么这些Activity都会托管在同一个进程中,这是因为他们在带的ApplicationInfo中的ProcessName都是一样的。
mPidsSelfLocked数组记录了PID,这个将会在应用进程跑起来后,将自己Attach到AM时,根据pid找到自己的前世:ProcessRecord.
2)android.app.ActivityThread进程启动
Android.app.ActivityThread进程建立后,将跳入到ActivityThread的main函数开始运行,进入消息循环。
应用进程使用thread.attach()发起AMS的AttachApplicationLocked调用,并传递 ActvitiyThread对象和CallingPid。AttachApplicationLocked将根据CallingPid在mPidsSelfLocked找到对应的ProcessRecord实例app,将ActvitiyThread放置app.thread中。这样应用进程和AMS建立起来双向连接。AM可以使用AIDL接口,通过app.thread可以访问应用进程的对象。
应用程序通过ActivityThread提供的框架,建立消息循环Looper和Handler。从前面的相关章节我们知道有Looper和Handler,整个系统就可以运作了。
为了更为系统的了解应用程序的建立时序及其涉及到数据操作,我给出了应用进程的建立过程示意图: