当前位置:首页 » 安卓系统 » androidstub

androidstub

发布时间: 2022-11-05 10:14:49

① android开发如何调试

能够在eclipse上运行调试应用程序之前,你必须为它创建一个启动项。启动项指定哪个工程将被启动,哪个activity开始工作,以及使用哪些模拟器选项等。
按照以下步骤为Eclipse版本的应用程序创建合适的启动项:
打开启动项管理工具。
在Eclipse 3.3 (Europa)的版本中,酌情选择 Run > Open RunDialog... or Run > Open Debug Dialog... 。
在Eclipse3.4 (Ganymede)版本中,酌情选择 Run > Run Configurations...or Run > Debug Configurations... 。
在左边的工程类型列表选择Android Application选择,双击(或者点击右键选择new),创建一个新的启动项。
输入启动项名称。
在Android标签中,浏览要开始的工程和Activity 。
在Target标签中,设置想要显示的屏幕及网络属性,以及其他任何模拟器启动选项。
你可以在Common标签中设置更多的选项.
按下Apply保存启动配置,或者按下Run或Debug()。
运行和调试应用程序
一旦你设定了工程和工程启动配置,你就可以按照以下的说明运行和调试应用程序了。
从eclipse主菜单,根据情况选择Run>Run 或者 Run>Debug,开始运行或者调试活动启动项。
注意,这里活动启动项是在运行配置管理中最最近一次选中的那个。它不一定就是在Eclipse Navigation 面板中选择的程序(如果有的话)
设置和修改活动启动项,可以使用启动项管理工具。如何获得启动项管理工具可以参考创建一个启动项
运行或调试应用程序将触发以下动作:
启动模拟器,如果他还没有开始运行。
编译工程, 如果在上次编译的基础上修改过代码,将重新编译。在模拟器上安装应用程序。
Run选项,开始运行程序。
Debug 在"Wait for debugger "模式下启动程序,然后打开调试窗口并将Eclipse java调试器和程序关联。
利用其他IDEs和工具开发Android应用程序
通常我们使用安装有ADT插件的eclipse Eclipse with the ADT plugin.来开发Android程序,这个插件将编辑,build和调试功能集成到IDE上。
然而,如果你想在其他的IDE上开发程序,例如IntelliJ,或者使用没有ADT插件的eclipse也可以。SDK提供了安装,编译,调试应用程序所需要的工具。
创建一个android工程
Android SDK包含一个activityCreator的程序,它将为工程产生多个stub文件和一个build文件。你可以用这个程序创建一个新的 Android工程或者在现有代码上创建工程,如SDK中包含的例子。对于linux 和Mac系统,SDK提供activityCreator.py,一个 Python脚本,Windows上则是activityCreator.bat一个批处理脚本。无论是哪种平台,用法是一样的。
按以下步骤运行activityCreator创建Android工程:
在命令行下,切换到SDK下的tools/目录下,为你的工程文件新建一个目录。如果你是在现有代码上创建工程,切换到程序的根目录下。
运行activityCreator。在命令行下,你必须指定完全合格的类名作为参数。如果你是创建一个全新的工程,这个类代表的与它同名的stub类和脚本文件。如果是在现有代码上创建工程,必须指定软件包中其中一个Activity类的名称。命令选项的脚本包括:
--out <folder> 设定输出目录。默认情况下输出目录为当前目录。如果你想为工程文件创建一个新的目录,可以使用这个选项来指向它。
--ide intellij, 在一个新的项目中生成IntelliJIDEA 工程文件。
这里有个例子:
~/android_linux_sdk/tools $ ./activityCreator.py --out myprojectyour.package.name.ActivityName
package: your.package.name
out_dir: myproject
activity_name: ActivityName
~/android_linux_sdk/tools $
activityCreator脚本生成以下文件和目录(但是不能重写已有文件):
AndroidManifest.xml 程序的清单文件,同时为工程指定Activity类。
build.xml 一个Ant文件,用来编译/打包应用程序。
src/your/package/name/ActivityName.java 你指定的输入Activity类。
your_activity.iml, your_activity.ipr, your_activity.iws [only with the-ide intelliJ flag] intelliJ工程文件
res/ 资源目录.
src/ 源代码目录.
bin/ build脚本的输出目录.
现在你可以将开发文件夹移到任何地方,但是记住,必须使用tool/文件夹下的adb程序将文件发送到模拟器上。因此你需要在你工作环境和tools/文件夹之间活动。
当然你需要避免移动SDK目录,因为它将打断编译脚本。(再重新build之前需要手动更新SDK的映射路径)
编译 android应用程序
使用activityCreator生成的Ant文件build.xml来编译程序
如果你没有,你可以通过Apache Ant home page得到Ant文件。安装它,并确定它在你的可执行文件路径下。
呼叫Ant之前,你需声明JAVA_HOME环境变量,并将它设置为JDK的安装路径。
注 意:在windows上,JDK默认的安装路径为"ProgramFiles",这个路径将会引起Ant失败,因为路径中间有空格。解决这个问题,你可以像这样指定环境变量 JAVA_HOME:JAVA_HOME=c:\Prora~1\Java\ 然而简单的解决方法是将JDK安装在没有空格的目录下。例如:c:\java\jdk1.6.0_02.
如果你还没有这么准备好,按照上面创建一个新的工程的介绍建立一个工程。
现在你可以为你的工程运行Ant编译文件,只需在build.xml同文件夹下输入ant即可。每次修改原文件或是资源,都需要重新运行ant,它将把最新版的应用程序打包以便deploy.
运行Android程序
运行一个编译好的程序,你需要用adb工具将.apk文件加载到模拟器的/data/app/目录下,用法如下面介绍。
启动模拟器(命令行下运行sdk目录下的/tools/emulator)。
模拟器切换到主画面(最好不要在程序运行的时候向模拟器安装程序,可以按home键离开应用程序)。
运 行adb,安装myproject/bin./<appname>.apk文件。例如,安装Lunar Lander 示例,命令行下,切换到SDK目录下的/sample/LunarLander子目录下,输入../../tools/adbinstall bin/LunarLander.apk
在模拟器中,打开可执行程序列表,卷动屏幕,选中并启动你的应用程序。
注意:当你第一次安装一个Activity时,你可能需要在启动项显示之前,或者其它程序调用它之前重新启动模拟器。因为软件包管理工具通常只有在模拟器启动时才能完全的审查manifests。
为程序附加调试器
这一节我们介绍如何在屏幕上显示调试信息(例如CPU使用率),以及如何将IDE和模拟器上运行的程序关联起来。
使用eclipse插件可以自动的生成调试器。但你也可以通过配置IDES来监听调试端口得到调试信息。
启动Dalvik Debug Monitor Server (DDMS) 工具 ,它在IDE和模拟器之间扮演着端口转换服务的角色。?
设置模拟器调试配置选项。例如,等到调试信息被加载后才启动应用程序。注意,很多调试选项无需DDMS也可以使用,例如模拟器上显示CPU的使用效率,或者屏幕的刷新频率。
配置IDE,使得调试时IDE与8700端口关联 .how to set up Eclipse to debug your project. 包含以下信息。
配置IDE附加调试端口
DDMS将为每一个虚拟机分配一个特殊的调试端口,这个端口在模拟器上可以找到。你必须将你的IDE与此端口(虚拟机上信息栏中有列出这些端口)关联或者是默认的端口8700。这样可以使IDE 连接到模拟器上程序列表中的任一个程序。
你的IDE需要能够关联模拟器上正在运行的程序,显示它的线程,并允许你挂起它,检查它的状态,设置断点。如果你在开发设置面板选择了“等待调试”,应用程序将等到Eclipse连接后才运行,所以你需要在连接之前设置断点。
修改正在调试的程序,或者在当前程序运行时选择“等待调试”将引起系统杀死这个应用程序。如果你的程序处于一种坏的状态,你可以使用方式杀死它,方法很简单,只需要设置和钩掉复选框。

② Android源码解析RPC系列(一)---Binder原理

看了几天的Binder,决定有必要写一篇博客,记录一下学习成果,Binder是Android中比较综合的一块知识了,目前的理解只限于JAVA层。首先Binder是干嘛用的?不用说,跨进程通信全靠它,操作系统的不同进程之间,数据不共享,对于每个进程来说,它都天真地以为自己独享了整个系统,完全不知道其他进程的存在,进程之间需要通信需要某种系统机制才能完成,在Android整个系统架构中,采用了大量的C/S架构的思想,所以Binder的作用就显得非常重要了,但是这种机制为什么是Binder呢?在Linux中的RPC方式有管道,消息队列,共享内存等,消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,这样就有两次拷贝过程。共享内存不需要拷贝,但控制复杂,难以使用。Binder是个折中的方案,只需要拷贝一次就行了。其次Binder的安全性比较好,好在哪里,在下还不是很清楚,基于安全性和传输的效率考虑,选择了Binder。Binder的英文意思是粘结剂,Binder对象是一个可以跨进程引用的对象,它的实体位于一个进程中,这个进程一般是Server端,该对象提供了一套方法用以实现对服务的请求,而它的引用却遍布于系统的各个进程(Client端)之中,这样Client通过Binder的引用访问Server,所以说,Binder就像胶水一样,把系统各个进程粘结在一起了,废话确实有点多。

为了从而保障了系统的安全和稳定,整个系统被划分成内核空间和用户空间
内核空间:独立于普通的应用程序,可以访问受保护的内存空间,有访问底层硬件设备的所有权限。
用户空间:相对与内核空间,上层运用程序所运行的空间就是用户空间,用户空间访问内核空间的唯一方式就是系统调用。一个4G的虚拟地址空间,其中3G是用户空间,剩余的1G是内核空间。如果一个用户空间想与另外一个用户空间进行通信,就需要内核模块支持,这个运行在内核空间的,负责各个用户进程通过Binder通信的内核模块叫做Binder驱动,虽然叫做Binder驱动,但是和硬件并没有什么关系,只是实现方式和设备驱动程序是一样的,提供了一些标准文件操作。

在写AIDL的时候,一般情况下,我们有两个进程,一个作为Server端提供某种服务,然后另外一个进程作为Client端,连接Server端之后,就 可以使用Server里面定义的服务。这种思想是一种典型的C/S的思想。值得注意的是Android系统中的Binder自身也是C/S的架构,也有Server端与Client端。一个大的C/S架构中,也有一个小的C/S架构。

先笼统的说一下,在整个Binder框架中,由系列组件组成,分别是Client、Server、ServiceManager和Binder驱动程序,其中Client、Server和ServiceManager运行在用户空间,Binder驱动程序运行内核空间。运行在用户空间中的Client、Server和ServiceManager,是在三个不同进程中的,Server进程中中定义了服务提供给Client进程使用,并且Server中有一个Binder实体,但是Server中定义的服务并不能直接被Client使用,它需要向ServiceManager注册,然后Client要用服务的时候,直接向ServiceManager要,ServiceManager返回一个Binder的替身(引用)给Client,这样Client就可以调用Server中的服务了。

场景 :进程A要调用进程B里面的一个draw方法处理图片。

分析 :在这种场景下,进程A作为Client端,进程B做为Server端,但是A/B不在同一个进程中,怎么来调用B进程的draw方法呢,首先进程B作为Server端创建了Binder实体,为其取一个字符形式,可读易记的名字,并将这个Binder连同名字以数据包的形式通过Binder驱动发送给ServiceManager,也就是向ServiceManager注册的过程,告诉ServiceManager,我是进程B,拥有图像处理的功能,ServiceManager从数据包中取出名字和引用以一个注册表的形式保留了Server进程的注册信息。为什么是以数据包的形式呢,因为这是两个进程,直接传递对象是不行滴,只能是一些描述信息。现在Client端进程A联系ServiceManager,说现在我需要进程B中图像处理的功能,ServiceManager从注册表中查到了这个Binder实体,但是呢,它并不是直接把这个Binder实体直接给Client,而是给了一个Binder实体的代理,或者说是引用,Client通过Binder的引用访问Server。分析到现在,有个关键的问题需要说一下,ServiceManager是一个进程,Server是另一个进程,Server向ServiceManager注册Binder必然会涉及进程间通信。当前实现的是进程间通信却又要用到进程间通信,这就好象蛋可以孵出鸡前提却是要找只鸡来孵蛋,确实是这样的,ServiceManager中预先有了一个自己的Binder对象(实体),就是那只鸡,然后Server有个Binder对象的引用,就是那个蛋,Server需要通过这个Binder的引用来实现Binder的注册。鸡就一只,蛋有很多,ServiceManager进程的Binder对象(实体)仅有一个,其他进程所拥有的全部都是它的代理。同样一个Server端Binder实体也应该只有一个,对应所有Client端全部都是它的代理。

我们再次理解一下Binder是什么?在Binder通信模型的四个角色里面;他们的代表都是“Binder”,一个Binder对象就代表了所有,包括了Server,Client,ServiceManager,这样,对于Binder通信的使用者而言,不用关心实现的细节。对Server来说,Binder指的是Binder实体,或者说是本地对象,对于Client来说,Binder指的是Binder代理对象,也就是Binder的引用。对于Binder驱动而言,在Binder对象进行跨进程传递的时候,Binder驱动会自动完成这两种类型的转换。

简单的总结一下,通过上面一大段的分析,一个Server在使用的时候需要经历三个阶段

1、定义一个AIDL文件
Game.aidl

GameManager .aidl

2、定义远端服务Service
在远程服务中的onBind方法,实现AIDL接口的具体方法,并且返回Binder对象

3、本地创建连接对象

以上就是一个远端服务的一般套路,如果是在两个进程中,就可以进程通信了,现在我们分析一下,这个通信的流程。重点是GameManager这个编译生成的类。

从类的关系来看,首先接口GameManager 继承 IInterface ,IInterface是一个接口,在GameManager内部有一个内部类Stub,Stub继承了Binder,(Binder实现了IBinder),并且实现了GameManager接口,在Stub中还有一个内部类Proxy,Proxy也实现了GameManager接口,一个整体的结构是这样的

现在的问题是,Stub是什么?Proxy又是什么?在上面说了在Binder通信模型的四个角色里面;他们的代表都是“Binder”,一个Binder对象就代表了所有,包括了Server,Clinet,ServiceManager,为了两个进程的通信,系统给予的内核支持是Binder,在抽象一点的说,Binder是系统开辟的一块内存空间,两个进程往这块空间里面读写数据就行了,Stub从Binder中读数据,Proxy向Binder中写数据,达到进程间通信的目的。首先我们分析Stub。

Stub 类继承了Binder ,说明了Stub有了跨进程传输的能力,实现了GameManager接口,说明它有了根据游戏ID查询一个游戏的能力。我们在bind一个Service之后,在onServiceConnecttion的回调里面,就是通过asInterface方法拿到一个远程的service的。

asInterface调用queryLocalInterface。

mDescriptor,mOwner其实是Binder的成员变量,Stub继承了Binder,在构造函数的时候,对着两个变量赋的值。

如果客户端和服务端是在一个进程中,那么其实queryLocalInterface获取的就是Stub对象,如果不在一个进程queryLocalInterface查询的对象肯定为null,因为不同进程有不同虚拟机,肯定查不到mOwner对象的,所以这时候其实是返回的Proxy对象了。拿到Stub对象后,通常在onServiceConnected中,就把这个对象转换成我们多定义AIDL接口。

比如我们这里会转换成GameManager,有了GameManager对象,就可以调用后querryGameById方法了。如果是一个进程,那直接调用的是自己的querryGameById方法,如果不是一个进程,那调用了就是代理的querryGameById方法了。

看到其中关键的一行是

mRemote就是一个IBinder对象,相对于Stub,Proxy 是组合关系(HAS-A),内部有一个IBinder对象mRemote,Stub是继承关系(IS-A),直接实现了IBinder接口。

transact是个native方法,最终还会回掉JAVA层的onTransact方法。

onTransact根据调用号(每个AIDL函数都有一个编号,在跨进程的时候,不会传递函数,而是传递编号指明调用哪个函数)调用相关函数;在这个例子里面,调用了Binder本地对象的querryGameById方法;这个方法将结果返回给驱动,驱动唤醒挂起的Client进程里面的线程并将结果返回。于是一次跨进程调用就完成了。

***Please accept mybest wishes for your happiness and success ! ***

③ android启动后怎么查看其里面的进程和线程

1)一个 Android 程序开始运行时,会单独启动一个Process。
默认情况下,所有这个程序中的Activity或者Service都会跑在这个Process。
默认情况下,一个Android程序也只有一个Process,但一个Process下却可以有许多个Thread。
2)一个 Android 程序开始运行时,就有一个主线程Main Thread被创建。该线程主要负责UI界面的显示、更新和控件交互,所以又叫UI Thread。

3)一个Android程序创建之初,一个Process呈现的是单线程模型--即MainThread,所有的任务都在一个线程中运行,所以,MainThread所调用的每一个函数,其耗时应该越短越好,而对于比较耗时的工作,应该交给子线程去做,以避免主线程(UI线程)被阻塞,导致程序出现ANR(Application not response)

一个Activity就运行在一个线程中吗?或者编码时,如果不是明确安排在不同线程中的两个Activity,其就都是在同一个线程中?那从一个Activity跳转到另一个Activity时,是不是跳出的那个Activity就处在睡眠状态了?
【答】 每个Activity都有一个Process属性,可以指定该Activity是属于哪个进程的。当然如果不明确指明,应该就是从属于默认进程(Application指定的,如其未指定,应该就是默认主进程)。

Android中有Task的概念,而同一个Task的各个Activity会形成一个栈,只有站定的Activity才有机会与用户交互。

原文地址:Android中的进程与线程 原文作者:江鹏

当应用程序的组件第一次运行时,Android将启动一个只有一个执行线程的Linux进程。默认,应用程序所有的组件运行在这个进程和线程中。然而,你可以安排组件运行在其他进程中,且你可以为进程衍生出其它线程。本文从下面几点来介绍Android的进程与线程:

1、进程

组件运行于哪个进程中由清单文件控制。组件元素——<activity>、<service>、<receiver>、<provider>,都有一个process属性可以指定组件运行在哪个进程中。这个属性可以设置为每个组件运行在自己的进程中,或者某些组件共享一个进程而其他的不共享。他们还可以设置为不同应用程序的组件运行在同一个进程中——假设这些应用程序共享同一个Linux用户ID且被分配了同样的权限。<application>元素也有process属性,为所有的组件设置一个默认值。

所有的组件都在特定进程的主线程中实例化,且系统调用组件是由主线程派遣。不会为每个实例创建单独的线程,因此,对应这些调用的方法——诸如View.onKeyDown()报告用用户的行为和生命周期通知,总是运行在进程的主线程中。这意味着,没有组件当被系统调用时应该执行很长时间或阻塞操作(如网络操作或循环计算),因为这将阻塞进程中的其它组件。你可以为长操作衍生独立的线程。

public boolean onKeyDown(int keyCode,KeyEvent event):默认实现KeyEvent.Callback.onKeyMultiple(),当按下视图的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然后释放时执行,如果视图可用且可点击。

参数

keyCode-表示按钮被按下的键码,来自KeyEvent
event-定义了按钮动作的KeyEvent对象

返回值

如果你处理事件,返回true;如果你想下一个接收者处理事件,返回false。

当内存剩余较小且其它进程请求较大内存并需要立即分配,Android要回收某些进程,进程中的应用程序组件会被销毁。当他们再次运行时,会重新开始一个进程。

当决定终结哪个进程时,Android会权衡他们对用户重要性的相对权值。例如,与运行在屏幕可见的活动进程相比(前台进程),它更容易关闭一个进程,它的活动在屏幕是不可见(后台进程)。决定是否终结进程,取决于运行在进程中的组件状态。关于组件的状态,将在后面一篇——组件生命周期中介绍。

2、线程

虽然你可能会将你的应用程序限制在一个进程中,但有时候你会需要衍生一个线程做一些后台工作。因为用户界面必须很快地响应用户的操作,所以活动寄宿的线程不应该做一些耗时的操作如网络下载。任何不可能在短时间完成的操作应该分配到别的线程。

线程在代码中是用标准的Java线程对象创建的,Android提供了一些方便的类来管理线程——Looper用于在线程中运行消息循环、Handler用户处理消息、HandlerThread用户设置一个消息循环的线程。

Looper类

该类用户在线程中运行消息循环。线程默认没有消息循环,可以在线程中调用prepare()创建一个运行循环;然后调用loop()处理消息直到循环结束。大部分消息循环交互是通过Handler类。下面是一个典型的执行一个Looper线程的例子,分别使用prepare()和loop()创建一个初始的Handler与Looper交互:

1. Android中进程与进程、线程与线程之间如何通信?
1)一个 Android 程序开始运行时,会单独启动一个Process。
默认情况下,所有这个程序中的Activity或者Service都会跑在这个Process。
默认情况下,一个Android程序也只有一个Process,但一个Process下却可以有许多个Thread。
2)一个 Android 程序开始运行时,就有一个主线程Main Thread被创建。该线程主要负责UI界面的显示、更新和控件交互,所以又叫UI Thread。

3)一个Android程序创建之初,一个Process呈现的是单线程模型--即MainThread,所有的任务都在一个线程中运行,所以,MainThread所调用的每一个函数,其耗时应该越短越好,而对于比较耗时的工作,应该交给子线程去做,以避免主线程(UI线程)被阻塞,导致程序出现ANR(Application not response)

一个Activity就运行在一个线程中吗?或者编码时,如果不是明确安排在不同线程中的两个Activity,其就都是在同一个线程中?那从一个Activity跳转到另一个Activity时,是不是跳出的那个Activity就处在睡眠状态了?
【答】 每个Activity都有一个Process属性,可以指定该Activity是属于哪个进程的。当然如果不明确指明,应该就是从属于默认进程(Application指定的,如其未指定,应该就是默认主进程)。

Android中有Task的概念,而同一个Task的各个Activity会形成一个栈,只有站定的Activity才有机会与用户交互。

原文地址:Android中的进程与线程 原文作者:江鹏

当应用程序的组件第一次运行时,Android将启动一个只有一个执行线程的Linux进程。默认,应用程序所有的组件运行在这个进程和线程中。然而,你可以安排组件运行在其他进程中,且你可以为进程衍生出其它线程。本文从下面几点来介绍Android的进程与线程:

1、进程

组件运行于哪个进程中由清单文件控制。组件元素——<activity>、<service>、<receiver>、<provider>,都有一个process属性可以指定组件运行在哪个进程中。这个属性可以设置为每个组件运行在自己的进程中,或者某些组件共享一个进程而其他的不共享。他们还可以设置为不同应用程序的组件运行在同一个进程中——假设这些应用程序共享同一个Linux用户ID且被分配了同样的权限。<application>元素也有process属性,为所有的组件设置一个默认值。

所有的组件都在特定进程的主线程中实例化,且系统调用组件是由主线程派遣。不会为每个实例创建单独的线程,因此,对应这些调用的方法——诸如View.onKeyDown()报告用用户的行为和生命周期通知,总是运行在进程的主线程中。这意味着,没有组件当被系统调用时应该执行很长时间或阻塞操作(如网络操作或循环计算),因为这将阻塞进程中的其它组件。你可以为长操作衍生独立的线程。

public boolean onKeyDown(int keyCode,KeyEvent event):默认实现KeyEvent.Callback.onKeyMultiple(),当按下视图的KEYCODE_DPAD_CENTER或KEYCODE_ENTER然后释放时执行,如果视图可用且可点击。

参数

keyCode-表示按钮被按下的键码,来自KeyEvent
event-定义了按钮动作的KeyEvent对象

返回值

如果你处理事件,返回true;如果你想下一个接收者处理事件,返回false。

当内存剩余较小且其它进程请求较大内存并需要立即分配,Android要回收某些进程,进程中的应用程序组件会被销毁。当他们再次运行时,会重新开始一个进程。

当决定终结哪个进程时,Android会权衡他们对用户重要性的相对权值。例如,与运行在屏幕可见的活动进程相比(前台进程),它更容易关闭一个进程,它的活动在屏幕是不可见(后台进程)。决定是否终结进程,取决于运行在进程中的组件状态。关于组件的状态,将在后面一篇——组件生命周期中介绍。

2、线程

虽然你可能会将你的应用程序限制在一个进程中,但有时候你会需要衍生一个线程做一些后台工作。因为用户界面必须很快地响应用户的操作,所以活动寄宿的线程不应该做一些耗时的操作如网络下载。任何不可能在短时间完成的操作应该分配到别的线程。

线程在代码中是用标准的Java线程对象创建的,Android提供了一些方便的类来管理线程——Looper用于在线程中运行消息循环、Handler用户处理消息、HandlerThread用户设置一个消息循环的线程。

Looper类

该类用户在线程中运行消息循环。线程默认没有消息循环,可以在线程中调用prepare()创建一个运行循环;然后调用loop()处理消息直到循环结束。大部分消息循环交互是通过Handler类。下面是一个典型的执行一个Looper线程的例子,分别使用prepare()和loop()创建一个初始的Handler与Looper交互:

2.1、远程过程调用(Remote procere calls,RPCs)

Android有一个轻量级的远程过程调用机制——方法在本地调用却在远程(另外一个进程中)执行,结果返回给调用者。这需要将方法调用和它伴随的数据分解为操作系统能够理解的层次,从本地进程和地址空间传输到远程进程和地址空间,并重新组装调用。返回值以相反方向传输。Android提供了做这些工作的所有代码,这样我们可以专注于定义和执行RPC接口本身。

一个RPC接口仅包含方法。所有的方法同步地执行(本地方法阻塞直到远程方法执行完成),即使是没有返回值。简言之,该机制工作原理如下:首先,你用简单的IDL(interface definition language,接口定义语言)声明一个你想实现的RPC接口。从这个声明中,aidl工具生成一个Java接口定义,提供给本地和远程进程。它包含两个内部类,如下图所示:

内部类有管理你用IDL定义的接口的远程过程调用所需要的所有代码。这两个内部类都实现了IBinder接口。其中之一就是在本地由系统内部使用,你写代码可以忽略它。另外一个是Stub,扩展自Binder类。除了用于有效地IPC(interprocess communication)调用的内部代码,内部类在RPC接口声明中还包含方法声明。你可以定义Stub的子类实现这些方法,如图中所示。

通常情况下,远程过程有一个服务管理(因为服务能通知系统关于进程和它连接的其它进程的信息)。它有由aidl工具生成的接口文件和Stub子类实现的RPC方法。服务的客户端仅有由aidl工具生成的接口文件。

下面介绍服务如何与它的客户端建立连接:

· 服务的客户端(在本地端的)应该实现onServiceConnected() 和onServiceDisconnected() 方法,因此当与远程服务建立连接成功和断开连接是会通知它。然后调用bindService() 建立连接。

· 服务的onBind()方法将实现为接受或拒绝连接,者取决于它接受到的意图(该意图传送到binServive())。如果连接被接受,它返回一个Stub子类的实例。

· 如果服务接受连接,Android调用客户端的onServiceConnected()方法且传递给它一个IBinder对象,返回由服务管理的Stub子类的一个代理。通过代理,客户端可以调用远程服务。

这里只是简单地描述,省略了一些RPC机制的细节。你可以查阅相关资料或继续关注Android开发之旅,后面将为你奉上。

2.2、线程安全方法

在一些情况下,你实现的方法可能会被不止一个线程调用,因此必须写成线程安全的。这对远程调用方法是正确的——如上一节讨论的RPC机制。当从IBinder进程中调用一个IBinder对象中实现的一个方法,这个方法在调用者的线程中执行。然而,当从别的进程中调用,方法将在Android维护的IBinder进程中的线程池中选择一个执行,它不在进程的主线程中执行。例如,一个服务的onBind()方法在服务进程的主线程中被调用,在onBind()返回的对象中执行的方法(例如,实现RPC方法的Stub子类)将在线程池中被调用。由于服务可以有一个以上的客户端,所以同时可以有一个以上的线程在执行同一个IBinder方法。因此,IBinder的方法必须是线程安全的。

同样,一个内容提供者可以接受其它进程产生的数据请求。虽然ContentResolver 和 ContentProvider 类隐藏进程通信如何管理的,对应哪些请求的ContentResolver 方法——query()、insert()、delete()、update()、getType(),在内容提供者的进程的线程池中被调用,而不是在这一进程的主线程中。因为这些方法可以同时从任意数量的线程中调用,他们也必须实现为线程安全的。

④ Android service 中的stub类是什么意思

stub是为了方便client,service交互而生成出来的代码。
AIDL(android 接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。
要使用AIDL,Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了。
交互过程client<-->proxy<-->stub<-->service

stub和proxy是为了方便client/service交互而生成出来的代码,这样client/service的代码就会比较干净,不会嵌入很多很难懂的与业务无关的代码

⑤ 安卓的安全机制

Android以Linux操作系统内核为基础,实现硬件设备驱动、进程和内存管理、网络协议栈、电源管理等核心系统功能。除此以外,Android还增加了一些面向移动设备的特有功能,如低内存管理LMK(Low Memory Killer)、匿名共享内存(Ashmem: Anonymous Shared Memory),以及进程间通信Binder机制。这些功能的增强进一步提升了Android在内存管理、进程间通信等方面的安全性。

Android之前的版本并不存在硬件抽象层。鉴于硬件厂商并不希望公开其设备驱动的源代码,Google对此将Linux内核驱动程序进行封装,屏蔽掉底层的实现细节,向上提供统一的接口,这就是硬件抽象层。



HAL(Hardware Abstraction Layer)规定了一套应用层对硬件层的读写和配置的统一接口,本质上是将硬件的驱动分为用户空间和内核空间,其中内核驱动程序运行在内核空间,HAL运行在用户空间。上图中的Stub,以so库的形式存在,可以理解为proxy。上层通过调用标识获得HAL的相关Stub,进而取得相应操作。

系统运行时库由系统类库和Android运行时构成。系统类库基本上用C/C++编写,基本功能说明如下:



当然,还有Android NDK(Native Development Kit),使得应用程序可以不依赖Dalvik虚拟机进行开发。Android运行时核心库提供android.os, android.net, android.media等核心API,而Dalvik虚拟机依赖Linux内核,实现进程隔离与线程调度管理、安全与异常管理、垃圾回收等功能,并被改进以适应低内存、低处理器速度的移动设备环境。

再往上就是应用程序框架层了。一系列的Android应用程序所需的类库,使得开发人员可以快速地进行程序开发,也可以通过继承实现个性化的扩展。如Activity Manager负责主线程ActivityThread的创建、Activity生命周期的维护,并为窗口提供交互的接口。

应用层就是与用户直接交互的应用程序,如SMS短信、图片浏览器、地图以及开发人员所开发的应用程序。

⑥ android应用程序开发中run和debug 有什么区别

能够在eclipse上运行调试应用程序之前,你必须为它创建一个启动项。启动项指定哪个工程将被启动,哪个activity开始工作,以及使用哪些模拟器选项等。
按照以下步骤为Eclipse版本的应用程序创建合适的启动项:
打开启动项管理工具。
在Eclipse 3.3 (Europa)的版本中,酌情选择 Run > Open RunDialog... or Run > Open Debug Dialog... 。
在Eclipse3.4 (Ganymede)版本中,酌情选择 Run > Run Configurations...or Run > Debug Configurations... 。
在左边的工程类型列表选择Android Application选择,双击(或者点击右键选择new),创建一个新的启动项。
输入启动项名称。
在Android标签中,浏览要开始的工程和Activity 。
在Target标签中,设置想要显示的屏幕及网络属性,以及其他任何模拟器启动选项。
你可以在Common标签中设置更多的选项.
按下Apply保存启动配置,或者按下Run或Debug()。
运行和调试应用程序
一旦你设定了工程和工程启动配置,你就可以按照以下的说明运行和调试应用程序了。
从eclipse主菜单,根据情况选择Run>Run 或者 Run>Debug,开始运行或者调试活动启动项。
注意,这里活动启动项是在运行配置管理中最最近一次选中的那个。它不一定就是在Eclipse Navigation 面板中选择的程序(如果有的话)
设置和修改活动启动项,可以使用启动项管理工具。如何获得启动项管理工具可以参考创建一个启动项
运行或调试应用程序将触发以下动作:
启动模拟器,如果他还没有开始运行。
编译工程, 如果在上次编译的基础上修改过代码,将重新编译。在模拟器上安装应用程序。
Run选项,开始运行程序。
Debug 在"Wait for debugger "模式下启动程序,然后打开调试窗口并将Eclipse Java调试器和程序关联。
利用其他IDEs和工具开发Android应用程序
通常我们使用安装有ADT插件的eclipse Eclipse with the ADT plugin.来开发Android程序,这个插件将编辑,build和调试功能集成到IDE上。
然而,如果你想在其他的IDE上开发程序,例如IntelliJ,或者使用没有ADT插件的eclipse也可以。SDK提供了安装,编译,调试应用程序所需要的工具。
创建一个android工程
Android SDK包含一个activityCreator的程序,它将为工程产生多个stub文件和一个build文件。你可以用这个程序创建一个新的 Android工程或者在现有代码上创建工程,如SDK中包含的例子。对于Linux 和Mac系统,SDK提供activityCreator.py,一个 Python脚本,Windows上则是activityCreator.bat一个批处理脚本。无论是哪种平台,用法是一样的。
按以下步骤运行activityCreator创建Android工程:
在命令行下,切换到SDK下的tools/目录下,为你的工程文件新建一个目录。如果你是在现有代码上创建工程,切换到程序的根目录下。
运行activityCreator。在命令行下,你必须指定完全合格的类名作为参数。如果你是创建一个全新的工程,这个类代表的与它同名的stub类和脚本文件。如果是在现有代码上创建工程,必须指定软件包中其中一个Activity类的名称。命令选项的脚本包括:
--out <folder> 设定输出目录。默认情况下输出目录为当前目录。如果你想为工程文件创建一个新的目录,可以使用这个选项来指向它。
--ide intellij, 在一个新的项目中生成IntelliJIDEA 工程文件。
这里有个例子:
~/android_linux_sdk/tools $ ./activityCreator.py --out myprojectyour.package.name.ActivityName
package: your.package.name
out_dir: myproject
activity_name: ActivityName
~/android_linux_sdk/tools $
activityCreator脚本生成以下文件和目录(但是不能重写已有文件):
AndroidManifest.xml 程序的清单文件,同时为工程指定Activity类。
build.xml 一个Ant文件,用来编译/打包应用程序。
src/your/package/name/ActivityName.java 你指定的输入Activity类。
your_activity.iml, your_activity.ipr, your_activity.iws [only with the-ide intelliJ flag] intelliJ工程文件
res/ 资源目录.
src/ 源代码目录.
bin/ build脚本的输出目录.
现在你可以将开发文件夹移到任何地方,但是记住,必须使用tool/文件夹下的adb程序将文件发送到模拟器上。因此你需要在你工作环境和tools/文件夹之间活动。
当然你需要避免移动SDK目录,因为它将打断编译脚本。(再重新build之前需要手动更新SDK的映射路径)
编译 android应用程序
使用activityCreator生成的Ant文件build.xml来编译程序
如果你没有,你可以通过Apache Ant home page得到Ant文件。安装它,并确定它在你的可执行文件路径下。
呼叫Ant之前,你需声明JAVA_HOME环境变量,并将它设置为JDK的安装路径。
注 意:在windows上,JDK默认的安装路径为"ProgramFiles",这个路径将会引起Ant失败,因为路径中间有空格。解决这个问题,你可以像这样指定环境变量 JAVA_HOME:JAVA_HOME=c:\Prora~1\Java\ 然而简单的解决方法是将JDK安装在没有空格的目录下。例如:c:\java\jdk1.6.0_02.
如果你还没有这么准备好,按照上面创建一个新的工程的介绍建立一个工程。
现在你可以为你的工程运行Ant编译文件,只需在build.xml同文件夹下输入ant即可。每次修改原文件或是资源,都需要重新运行ant,它将把最新版的应用程序打包以便deploy.
运行Android程序
运行一个编译好的程序,你需要用adb工具将.apk文件加载到模拟器的/data/app/目录下,用法如下面介绍。
启动模拟器(命令行下运行sdk目录下的/tools/emulator)。
模拟器切换到主画面(最好不要在程序运行的时候向模拟器安装程序,可以按home键离开应用程序)。
运 行adb,安装myproject/bin./<appname>.apk文件。例如,安装Lunar Lander 示例,命令行下,切换到SDK目录下的/sample/LunarLander子目录下,输入../../tools/adbinstall bin/LunarLander.apk
在模拟器中,打开可执行程序列表,卷动屏幕,选中并启动你的应用程序。
注意:当你第一次安装一个Activity时,你可能需要在启动项显示之前,或者其它程序调用它之前重新启动模拟器。因为软件包管理工具通常只有在模拟器启动时才能完全的审查manifests。
为程序附加调试器
这一节我们介绍如何在屏幕上显示调试信息(例如CPU使用率),以及如何将IDE和模拟器上运行的程序关联起来。
使用eclipse插件可以自动的生成调试器。但你也可以通过配置IDES来监听调试端口得到调试信息。
启动Dalvik Debug Monitor Server (DDMS) 工具 ,它在IDE和模拟器之间扮演着端口转换服务的角色。?
设置模拟器调试配置选项。例如,等到调试信息被加载后才启动应用程序。注意,很多调试选项无需DDMS也可以使用,例如模拟器上显示CPU的使用效率,或者屏幕的刷新频率。
配置IDE,使得调试时IDE与8700端口关联 .how to set up Eclipse to debug your project. 包含以下信息。
配置IDE附加调试端口
DDMS将为每一个虚拟机分配一个特殊的调试端口,这个端口在模拟器上可以找到。你必须将你的IDE与此端口(虚拟机上信息栏中有列出这些端口)关联或者是默认的端口8700。这样可以使IDE 连接到模拟器上程序列表中的任一个程序。
你的IDE需要能够关联模拟器上正在运行的程序,显示它的线程,并允许你挂起它,检查它的状态,设置断点。如果你在开发设置面板选择了“等待调试”,应用程序将等到Eclipse连接后才运行,所以你需要在连接之前设置断点。
修改正在调试的程序,或者在当前程序运行时选择“等待调试”将引起系统杀死这个应用程序。如果你的程序处于一种坏的状态,你可以使用方式杀死它,方法很简单,只需要设置和钩掉复选框。

⑦ android stub.asinterface是什么意思

参考如下博客内容:
IxxxxService.Stub.asInterface(IBinder obj) :
这个函数是干啥用呢?首先当bindService之后,客户端会得到一个Binder引用,是Binder 哟,不是IxxxxService.Proxy实例,那这样的话,我们第一个想法是利用Binder引用作为参数实例化出一个IxxxxService.Proxy。Ok, 但如果服务端和客户端都是在同一个进程呢,还需要利用IPC吗?这样就不需要了,直接将IxxxxService当做普通的对象调用就成了。Google 的同志们他们利用IxxxxService.Stub.asInterface函数对这两种不同的情况进行了统一,也就是不管你是在同一进程还是不同进程,那么在拿到Binder引用后,调用IxxxxService.Stub.asInterface(IBinder obj) 即可得到一个IxxxxService 实例,然后你只管调用IxxxxService里的函数就成了。

⑧ Android常见知识点

跳槽无非就是钱少了或不爽了,无论怎么样,记住:
不要裸辞!
不要裸辞!
不要裸辞!
为什么呢?
1、裸辞就没有钱拿了,还不如骑驴找马。
2、裸辞之后如果一个月内没有找到工作,那么社保就会断了,除非你自己找渠道交了。
3、裸辞之后真的会很颓废!
当初还在上班的时候就想着,裸辞了,首先花几天时间吧简历完善一下,把知识点恶补一下,然后投简历,面试,妥妥的妥妥。
结果呢?每次裸辞之后都是:
首先躺尸一个星期;
然后用了一个星期才慢吞吞的改完简历;
然后海投,没回复,修改简历;
再次海投,面试,被虐得体无完肤,怀疑人生;
再改简历,再海投,一不小心中了。

当然海投也是有个目标范围的。

如果不是裸辞,那么现在应该还是在公司上班,在完成工作之余,就会逼着自己复习知识点了,起码不会在家堕落。在家不上班就是睡觉、看电影,樯橹灰飞烟灭,所以不要裸辞。

然并卵,我依然裸辞了。请假面试真的很烦。

onPause,假如从ActivityA启动B,如果B是透明的,则不会回调A的onStop方法。

方法一:

方法二:

1、写好动画文件 R.anim.enter 、 R.anim.exit
2、调用 overridePendingTransition 设置动画

引申:如Activity设置为singleInstance,则应该怎么设置跳转动画?

1、 startService 启动方与Service并没有关联,只有当Service调用 stopSelf 或者其它组件调用 stopService 的时候服务才会终止。

2、 bindService 启动方绑定Service,并且可以通过Binder与之交互,当启动方销毁时,也会自动unbindService,当所有启动方都unbindService之后,Service也就自动销毁了。

为什么呢?官方文档是这样写的:

大概意思是 onReceive() 执行完毕之后,它所在的进程就会变成低优先级进程,极易被系统杀死。

分两种情况分析一下:
一、收到广播的时候,应用正在运行:
此时如果没有在Manifest中设置了独立进程,则 onReceive() 就直接在主进程主线程执行,这里很明显不能执行耗时操作。
二、收到广播的时候,应用没有启动:
这时候系统会启动一个进程去执行 onReceive() ,(如果Manifest中没有设置进程名,则进程名为包名),(插一句,所有进程都会创建一个Application实例),当onReceive执行完毕之后,此进程就变成低优先级了,随时有可能被系统杀死,如果你在onReceive里面启动了线程执行耗时任务,那很有可能子线程没执行完毕,进程就被杀死了,进程没了,线程自然就挂了。

那么确实要执行耗时操作呢,怎么办?
方法一:goAsync()

方法二:schele a JobService from the receiver using the JobScheler

三种实现方法
1、继承现有的组件,如TextView等,进行拓展。
2、继承ViewGroup,自定义布局。
3、继承View,在onDraw()中描绘。

onMeasure()

onLayout()

onDraw()

其它

attachToRoot 从字面理解就是是否绑定到 root 上面去了。
1、 attachToRoot=true :则返回的view为root的子view;
2、 attachToRoot=false :则返回的view是个单独的view,传入的root只是提供一些参数给view使用而已。

那么这里不传入 attachToRoot 呢?那就看root是否为空了,如果传入root不为空,则默认绑定到root,作为root的子view返回。

也就是所谓的Frame动画。指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果。
可以通过插入器 Interpolator 控制动画的变化速度。

也就是所谓补间动画。指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有 AlphaAnimation 、 TranslateAnimation 、 ScaleAnimation 、 RotateAnimation 四种。
注意:只是在视图层实现了动画效果,并没有真正改变View的属性。

属性动画,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。
注意:Android 3.0(API 11)以上才支持。
最常用的类有 ObjectAnimator

P.S. 我不明白cancel存在的意义。
另外, DialogFragment 是没有cancel的。

ping

内存大致分为三个区:栈区、堆区、方法区。

栈区

堆区

方法区

JAVA不允许手动释放内存,只能通过垃圾回收程序不定期对那些不再被引用的对象进行回收。

那么怎么判断哪些对象需要回收?

1、引用计数法
就是给对象添加一个引用计数器,引用对象时+1,引用失效时-1。但是这种方法解决不了对象相互引用的情况。

2、可达性分析法
通过一系列“GCRoots”对象作为起点进行搜索,当GCRoots和一个对象之间没有可达路径,则认为此对象不可用,但是不可用不一定会成为可回收对象。

编写AIDL文件,定义接口。
编译生成JAVA文件。
定义进程级Service,onBind中返回Interface.Stub()。
onServiceConnected中Interface aidl = Interface.Stub.asInterface(service);

把已修复的class文件打包成dex文件,网络传输到用户手机中,利用类加载器把这些类加载到类队列的前面即可。

【未完待续】

如果公司录用我,不管是三年还是五年,首先我都会先把公司的任务做好,然后不断深入研究Android的相关技术,特别是Android源码,了解Android底层原理,以便更好的优化性能,避免一些不必要的奇葩问题,还有就是研究一些新的框架的原理,学习别人的思维。最后就是学习周边语言,比如后台,前端等等。

⑨ android中 throw new RuntimeException("Stub!");是干什么用的为什么几乎每个接口函数里都有谢谢!

抛出运行时异常

热点内容
基因工程常用药配置遵循哪些原则 发布:2024-05-22 00:08:38 浏览:271
es买哪个配置的最多 发布:2024-05-21 23:57:23 浏览:695
阿里云服务器国外 发布:2024-05-21 23:46:39 浏览:78
双数据库 发布:2024-05-21 23:42:23 浏览:152
linuxip设置命令 发布:2024-05-21 22:52:56 浏览:852
aspnetfile上传 发布:2024-05-21 22:28:58 浏览:671
华为nm存储卡卡刷 发布:2024-05-21 22:25:23 浏览:601
sql注入过程 发布:2024-05-21 22:20:07 浏览:949
c并行编程 发布:2024-05-21 22:10:00 浏览:150
爱比较服务器怎么开 发布:2024-05-21 22:00:42 浏览:668