安卓手机已持手定角度怎么微信如何解除持卡人

后使用快捷导航没有帐号?
其他登录方式
—— 新手入门 ——
—— 智友精华 ——
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:13 编辑
注意Android是應用框架,不是一般OS平台
在上一節課程裡,特別強調應用框架的神祕力量,必須由Android的設計人角度去看它。不一定要成為框架設計人,但從他的角度和觀點能深刻觀察框架的魅力的源頭。在本課程的第一本教科書&&Google Android 應用框架原理與程式設計 36技&&裡(第1.5節),就提到常見的迷思:
  1.5&&框架與OS之關係:常見的迷思
  1.5.1&&迷思
  許多人從空間角度去想像OS與應用框架之間的關係。的確,OS(如Linux或Windows)像木板床,應用框架像彈簧床墊,其擺在木版床上。而應用程式則像睡在床墊上的人。這個觀點是對的(如圖1-4所示)。 然而,許多人順勢推論他們之間的互動關係如下圖:
07:39 上传
圖1-5&&常見的迷思
  乍看之下,似乎蠻合理的,其實是個迷思。請你換個角度,採取另一個觀點,如下圖,更容易體會框架的角色和涵意,此新觀點如下圖1-6所示。
  回想一下,您寫傳統程式時,主控權掌握在程式手中,其決定如何呼叫庫存函數﹔就像棒球比賽的「投手」一樣。反之,使用框架時,您的程式則擔任「捕手」之角色。盼您在使用框架時,能有這種心理準備(Mindset) 。& &&&
07:39 上传
圖1-6&&較合理的觀點
  由於高煥堂 老師於1995年就寫了一本 &&應用框架設計方法&&的書,至今仍然是唯一的應用框架設計中文書籍。他特別提醒Android的開發者,不要僅僅成為愚公移山故事裡的&愚公&,只顧挑畚箕,有時也從畚箕設計人角度看看畚箕、山、土及愚公。高老師特別在北京的程序員雜誌發表一篇短文:&&基類與愚公移山&&,被廣為流傳.
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:13 编辑
Android裡的類別繼承及物件組合
在Android裡定義了如下的類別繼承(Class Inheritance)體系:
07:42 上传
還有如下的物件組合(Object Composition)關係:
07:42 上传
ViewGroup的子孫類別(如下圖的LinearLayout),也自然繼承了上圖的組合關係:
07:42 上传
同樣地,View的子孫類別也具有同樣的繼承,可推導出如下之組合關係:
07:42 上传
這些是Android已經提供的基類(Base Class)。
  在這裡,話插一下,我在北京程序員雜誌上寫的&&基類與愚公移山&&一文裡,我稱之為『畚箕』。Android應用程式的開發者就如同挑畚箕的人,在中華歷史上,有個家喻戶曉的偉大人物就是『愚公』,它是挑畚箕的人,想把泰山的土一擔一擔挑去填北海。現在,我就來扮演愚公的角色,挑一擔(寫個Android應用程式)給你看看,但是請你不要叫我愚公就是。此外,我這個超級愚公還可以一根扁擔挑3個畚箕呢!!
  首先建立一個Android Project:
07:42 上传
我這個愚公希望手機畫面出現如下:
07:42 上传
在畫面上輸入一個字串,並按下&OK&時,就在畫面title區輸出了該字串:
07:42 上传
現在開始寫程式了,拿著一根扁擔(Layout)和兩三個畚箕(一個EditText、和兩個Button)。
程式碼如下:
package com.misoo.
import android.app.A
import android.graphics.C
import android.os.B
import android.view.V
import android.view.View.OnClickL
import android.widget.B
import android.widget.EditT
import android.widget.LinearL
public class ac01 extends Activity implements OnClickListener {
& && && &&&private final int WC = LinearLayout.LayoutParams.WRAP_CONTENT;
& && && &&&private final int FP = LinearLayout.LayoutParams.FILL_PARENT;
& && && &&&private Button btn, btn2;
& && && &&&private EditT
& && && &&&
& && && &&&@Override
& & public void onCreate(Bundle savedInstanceState) {
& && &&&super.onCreate(savedInstanceState);
& && &&&this.show_layout();
& & public void show_layout(){
& && &&&LinearLayout layout = new LinearLayout(this);
& && && &layout.setOrientation(LinearLayout.VERTICAL);
& && && &et = new EditText(this);
& && && &LinearLayout.LayoutParams param =
& && && && && & new LinearLayout.LayoutParams(FP, WC);
& && && &layout.addView(et, param);
& && && &btn = new Button(this);
& && && &LinearLayout.LayoutParams param2 =
& && && && & new LinearLayout.LayoutParams(WC, WC);
& && && &param2.topMargin = 5;
& && && &btn.setText(&OK&);
& && && &btn.setBackgroundResource(R.drawable.x_blue3);
& && && &btn.setOnClickListener(this);
& && && &layout.addView(btn, param2);
& && && &btn2 = new Button(this);
& && && &btn2.setText(&Exit&);
& && && &btn2.setTextColor(Color.RED);
& && && &btn2.setBackgroundResource(R.drawable.x_gray3);
& && && &btn2.setOnClickListener(this);
& && && &layout.addView(btn2, param2);
& && && &setContentView(layout);
& && && &&&public void onClick(View v) {
& && && && && && && &if(v == btn)
& && && && && && && && && && &&&setTitle(et.getText());
& && && && && && && &else if(v == btn2)
& && && && && && && && && && &&&finish();
& && && &&&}
透過layout扁擔的addView()函數就將畚箕一個一個挑起來了。
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:14 编辑
佈局在Android軟體開發上的重要角色
如果以SaaS(Software as a Service)的觀念來看Layout,會更清楚它的角色。如果以舞台劇的一『幕』來比喻Layout,會更傳神。一幕就是一個劇情的片段,此片段有其獨特的演出意涵,也是有頭有尾的完整片段。從SaaS的觀念來說,一個Layout是一個有其獨特目標的服務(Service)片段,或稱為小服務。這些小服務可以組合成為更完整更大的服務(或劇本)。
& && && &依據SaaS的概念,Service是有幕後的軟體類別或模組所提供、支撐或實現的。那麼,Layout背後的軟體模組是甚麼呢?答案是:Activity類別。有關於這些Layout的事件的處理程序都寫在Activity類別裡。不同的Activity類別可由不同的開發者負責開發。所以Activity可視為開發的分工單位。不同的開發者發揮其獨特的專業能力而開發出獨特的Activity類別,提供一些獨特的服務(即Layout)。
& && &&&Activity類別像樹枝,Layout像樹葉,而Android應用程式的用戶就像在樹葉上跑來跑去的金龜蟲。那麼,Android應用程式的角色就是將一系列來自不同Activity的Layout串聯起來。也就是那隻金龜蟲的行動軌跡了。
  那麼,Android應用程式又如何串聯這些Layout呢? 在Android平台裡,有個Intent類別。Android應用程式藉由Intent物件來與Android應用框架(Application Framework)核心進行溝通,請求Android框架核心來物色合適的Activity來提供其Layout,來進行服務。至於一個Activity到底提供甚麼目的的服務呢? 則寫在AndroidManifest.xml的Activity裡的Filter裡,基於Filter的條件而找到適當的服務,及其背後的Activity類別。該Activity再透過Layout而展現其服務。
& && & 一般而言,一個應用程式常包含多個獨立的服務流程,通稱為Use&&Case。而每一個Use Case都是由許多Layout提供的服務所組成。而Layout又是由Activity類別的多個函數來聯合服務。因此,傳統的UML和OOAD裡大家所熟悉的用例(Use Case)圖和類別(Class)圖,只要加上一個Layout的角色就能全部派上用場了。
  當我們將Layout視為服務時,SOA(Service-Oriented Architecture)和SaaS(Software as a Service)的兩項新的軟體開發技術,也能派上用場了。因之,Layout扮演一個極為重要的角色,連結了最新的軟體開發技術與Android最新的軟體開發平台,將為Android軟體開發團隊帶來可靠的開發技術和工具,也將為Android應用軟體帶來極高的品質和可靠度。
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:14 编辑
Android的IBinder介面及其安全性機制
Activity物件與Service物件在不同的進程(Process)裡執行,各有不同的UID(Unix user ID)。由於各自獨立執行,所以Activity物件通常依賴Intent物件去請求Android啟動所需要的Service。
  就Service物件的開發者而言,Activity物件是屬於外界(因為兩者在不同的進程裡執行)的軟體,也大多是別人開發的。那麼,Service物件如何確定這外來的物件是善意的呢? 這就是安全性的問題了。在Service類別裡,可以做權限的檢查,其常用指令如下圖:
07:45 上传
當Service確認了對方的善意,就將IBinder介面的參考(Reference)傳給Activity物件。Activity物件就能透過IBinder介面去使用Binder的服務了。如下圖:
07:45 上传
當Activity呼叫IBinder的transact()等函數時,會反向呼叫NotifyBinder子類別的onTransact()函數。此時,也可以進行安全檢驗,例如下圖裡的指令:
int uid = Binder.getCallingUID();
  就能取得對方UID來檢驗它的身分等。還可以進行checkCallingPermission()等檢驗。如下圖:
07:45 上传
經檢驗而確認來客是善意的,就啟動BinderServer(如影音播放器)來提供實質的服務。
  以上是就Service的開發者角度來看Android的IBinder的安全機制的有關概念。至於Android範例程式碼,在此節錄文章裡,就省略了。
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:16 编辑
認識Android的UID與權限
由於每個應用程式都有個UID,只有帶著此UID,才能存取該UID所涵蓋的有關資料。所以如果AP-1與AP-2的UID不同,則在預設(Default)情況下,雙方都無法讀取對方的資料。這種分而治之的方式,可以減輕駭客軟體的惡意傷害資料,提升手機的安全性。
  當手機使用者(即User)下載你(即開發者)的應用程式,在安裝(Install)時,Android就會給予一個UID。這個UID可連結到該應用程式的 AndroidManifest.xml檔案的內容。所以User在安裝你的應用程式時,在螢幕上的視窗裡可以檢視這個AndroidManifest.xml檔案的內容。在檢視時,用戶會看到你對應用程式的目的、權限等說明。當你接受這支程式的意圖、權限說明之後,Android就安裝它,並給它一個UID。萬一在你的應用程式執行期間有越軌(企圖做出非權限範圍)的行為時,用戶將會得到Android的警告訊息。
  有一些特殊情形下,兩支應用程式是可以持有一樣的UID。例如,同一位開發者撰寫的應用程式,常常需要推出新版本,這兩種版本的程式可以持有一樣的UID, 才有權限去將舊版程式所產生的資料拷貝轉移到新版軟體裡。
  一個用戶在其使用手機的用例(Use Case)裡,通常由一個Activity啟動開始,透過Intent物件去啟動其他的Activity、Service、ContentProvider等具有不同UID的一連串應用程式,才能滿足一個用例的目標。在傳統電腦上,UID是跟隨著「人」,一個用戶持著一個UID就能執行一連串的應用程式,而且在預設條件下是可以互相共享資料。但是在Android裡,這一連串的應用程式是各有自己的UID,而且可能都持著不同的UID,原則上是不能任意存取對方的資料。
  UID與AndroidManifest.xml檔案的連結除了可以保護各程式的私有資料之外,還可以禁止程式越權使用手機的各項資源。例如,開發者在AndroidManifest.xml檔案裡表明此程式有READ_CONTACTS的授權。用戶在安裝此應用程式時,檢視過AndroidManifest.xml的授權內涵,而且接受之。此應用程式就能合法地存取手機裡的通訊錄資料,甚至授權撥打電話、發簡訊等等。
  剛才提到過,一個用戶的用例(Use Case)裡,通常由多個不同UID的Activity、Service、ContentProvider等一連串的應用程式所串接,才能滿足用例的目標。此時,如果它們都必須存取通訊錄的話,必須都持有相同的READ_CONTACTS授權才行。
  以上就應用程式的開發者、使用者的角度來說明Android的UID之意義和用法。至於Android如何運用Linux的進程(Process)機制及Android的特殊管理政策,在此講義的節錄版裡,就省略之。
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:16 编辑
自己编译Google Android内核的Linux源码
这是之前自己在实验室试验时候的文章了,今天才发现还没有发出来,就整理了一下放出。Google推出了Android平台所基于的Linux的源码,在之前的相关文章中我也提到了这一点,除了比较该内核和标准内核之间的差异外,我们还可以自己通过源码来编译出自己的内核镜像。虽然目前编译出的镜像是和默认镜像一样的,但是这步成功,会对以后的系统移植有极大帮助。
  下面就是比较详细的步骤。首先,我们知道,Android的默认硬件处理器是ARM的,因此我们需要在自己的host机器上构建交叉编译环境。来到CodeSourcery,()选择ARM EABI 以及IA32 GNU/Linux,直接下载即可。然后从这里()获得内核源代码,准备工作就完成了。
  然后就是配置交叉编译链并解压缩源代码。建议这里把交叉编译工具的路径添加到PATH中,以后也方便。
  好,接下来就是常规的编译内核步骤了。首先需要配置文件。我们编译所需要的配置文件存在于Android运行系统中的proc目录下,具体是/proc/config.gz,因此,需要将其导出来。打开模拟器emulator -console,然后 在另一个终端下使用命令
adb pull /proc/config.gz ./
  这样,config.gz就被转移到当前目录下了。解压缩,重命名为.config,放到kernel,也就是源代码解压缩后的目录下,这就是我们编译系统需要用的配置文件。
  然后修改Makefile,指定成我们刚下载的交叉编译工具:
CROSS_COMPILE=/home/windstorm/Work/Android/arm-2007q3/bin/arm-none-eabi-
  另外,2.6.23的内核增加的build-id在这里不能用,必须去掉
 #LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,
 $(call ld-option, -Wl$(comma)–build-id,))
  如果不去掉,编译出来的内核有4.3M大,且模拟器无法加载。我还不是很清楚build-id在这里不能用的原因,知道的朋友请不吝赐教,谢谢。最后就直接make了。生成出来的镜像自动保存为arch/arm/boot/zImage,用ll看,是和原始镜像sdk/tools/lib/images/kernel-qemu的大小一样的。
 最后,就是通过emulator加载自己编译的内核,看看能否成功运行了
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:17 编辑
如何获得按键的键值
public class Display extends View
省略N-多代码!
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.e(&Key Event&,&KeyPressed :&+keyCode+ &KeyEvent :&+ event.getDeviceId());
if(nowDisplayable.getScreenMode()&&nowDisplayable.isActiveSoftKeyList(keyCode,event))
switch(keyCode)
case Displayable.LEFTSOFTKEY:
nowDisplayable.ChangeState(true);
case Displayable.RIGHTSOFTKEY:
nowDisplayable.ChangeState(false);
case Displayable.UP:
nowDisplayable.nextCommand();
case Displayable.DOWN:
nowDisplayable.prevCommand();
case Displayable.FIRE:
nowDisplayable.activeCurrentCommand();
nowDisplayable.keyPressed(keyCode);
// return super.onKeyDown(keyCode, event);
贴一段我写的代码吧..这是在View获得按键相应的函数. onKeyDown相当于J2me的KeyPressed,onKeyUp相当于keyR
还有现在我还没找到能代替J2me中 System.out.println()的函数
不过Log.e()这个也能起到类似的效果.
需要import android.util.LJose_z
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:18 编辑
Android的IPC机制Binder的各个部分 1
第一部分 Binder的组成
  1.1 驱动程序部分驱动程序的部分在以下的文件夹中:
kernel/include/linux/binder.h
kernel/drivers/android/binder.c
  binder驱动程序是一个miscdevice,主设备号为10,此设备号使用动态获得(MISC_DYNAMIC_MINOR),其设备的节点为:
/dev/binder
  binder驱动程序会在proc文件系统中建立自己的信息,其文件夹为/proc/binde,其中包含如下内容:
proc目录:调用Binder各个进程的内容
state文件:使用函数binder_read_proc_state
stats文件:使用函数binder_read_proc_stats
transactions文件:使用函数binder_read_proc_transactions
transaction_log文件:使用函数binder_read_proc_transaction_log,其参数为binder_transaction_log (类型为struct binder_transaction_log)
failed_transaction_log文件:使用函数binder_read_proc_transaction_log 其参数为
binder_transaction_log_failed (类型为struct binder_transaction_log)
  在binder文件被打开后,其私有数据(private_data)的类型:
struct binder_proc
  在这个数据结构中,主要包含了当前进程、进程ID、内存映射信息、Binder的统计信息和线程信息等。
  在用户空间对Binder驱动程序进行控制主要使用的接口是mmap、poll和ioctl,ioctl主要使用的ID为:
#define BINDER_WRITE_READ& && &&&_IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT&&_IOW('b', 3, int64_t)
#define BINDER_SET_MAX_THREADS& &_IOW('b', 5, size_t)
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int)
#define BINDER_SET_CONTEXT_MGR& &_IOW('b', 7, int)
#define BINDER_THREAD_EXIT& && & _IOW('b', 8, int)
#define BINDER_VERSION& && && &&&_IOWR('b', 9, struct binder_version)
  BR_XXX等宏为BinderDriverReturnProtocol,表示Binder驱动返回协议。
  BC_XXX等宏为BinderDriverCommandProtocol,表示Binder驱动命令协议。
  binder_thread是Binder驱动程序中使用的另外一个重要的数据结构,数据结构的定义如下所示:
struct binder_thread {
& && &struct binder_proc *
& &&&struct rb_node rb_
& &&&struct binder_transaction *transaction_
& &&&struct list_
& &&&uint32_t return_
& &&&uint32_t return_error2;
& &&&wait_queue_head_
& &&&struct binder_
  binder_thread 的各个成员信息是从rb_node中得出。
  BINDER_WRITE_READ是最重要的ioctl,它使用一个数据结构binder_write_read定义读写的数据。
struct binder_write_read {
& &&&signed long write_
& &&&signed long write_
& &&&unsigned long write_
& &&&signed long read_
& &&&signed long read_
& &&&unsigned long read_
1.2 servicemanager部分& && &&&servicemanager是一个守护进程,用于这个进程的和/dev/binder通讯,从而达到管理系统中各个服务的作用。
  可执行程序的路径:
   /system/bin/servicemanager& && &&&
开源版本文件的路径:
frameworks/base/cmds/servicemanager/binder.h
frameworks/base/cmds/servicemanager/binder.c
frameworks/base/cmds/servicemanager/service_manager.c
  程序执行的流程:
open():打开binder驱动
mmap():映射一个128*1024字节的内存
ioctl(BINDER_SET_CONTEXT_MGR):设置上下文为mgr
   进入主循环binder_loop()
& && && && & ioctl(BINDER_WRITE_READ),读取
& && && && && && && &&&binder_parse()进入binder处理过程循环处理
& && && &binder_parse()的处理,调用返回值:
  当处理BR_TRANSACTION的时候,调用svcmgr_handler()处理增加服务、检查服务等工作。各种服务存放在一个链表(svclist)中。其中调用binder_等开头的函数,又会调用ioctl的各种命令。
& && &&&处理BR_REPLY的时候,填充binder_io类型的数据结
  1.3 binder的库的部分
  binder相关的文件作为Android的uitls库的一部分,这个库编译后的名称为libutils.so,是Android系统中的一个公共库。
  主要文件的路径如下所示:
frameworks/base/include/utils/*
frameworks/base/libs/utils/*
  主要的类为:
RefBase.h :
  引用计数,定义类RefBase。
Parcel.h :
  为在IPC中传输的数据定义容器,定义类Parcel
IBinder.h:
  Binder对象的抽象接口, 定义类IBinder
Binder.h:
  Binder对象的基本功能, 定义类Binder和BpRefBase
BpBinder.h:
BpBinder的功能,定义类BpBinder
IInterface.h:
  为抽象经过Binder的接口定义通用类,
  定义类IInterface,类模板BnInterface,类模板BpInterface
ProcessState.h
  表示进程状态的类,定义类ProcessState
IPCThreadState.h
  表示IPC线程的状态,定义类IPCThreadState
  在IInterface.h中定义的BnInterface和BpInterface是两个重要的模版,这是为各种程序中使用的。
BnInterface模版的定义如下所示:
template&typename INTERFACE&
class BnInterface : public INTERFACE, public BBinder
  virtual sp&IInterface&&&queryLocalInterface(const String16& _descriptor);
  virtual String16& && &&&getInterfaceDescriptor()
protected:
& & virtual IBinder*& && &&&onAsBinder();
  BnInterface模版的定义如下所示:
template&typename INTERFACE&
class BpInterface : public INTERFACE, public BpRefBase
& && && && && && && && && & BpInterface(const sp&IBinder&& remote);
protected:
& & virtual IBinder*& & onAsBinder();
  这两个模版在使用的时候,起到得作用实际上都是双继承:使用者定义一个接口INTERFACE,然后使用BnInterface和BpInterface两个模版结合自己的接口,构建自己的BnXXX和BpXXX两个类。
& && && &DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE两个宏用于帮助BpXXX类的实现:
#define DECLARE_META_INTERFACE(INTERFACE)& && && && && && && && && && &
& & static const String16& && && && && && && && && && && &&&
& & static sp&I##INTERFACE& asInterface(const sp&IBinder&& obj);& && &&&
& & virtual String16 getInterfaceDescriptor()& && && && && && &&&
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)& && && && && && && &&&
& & const String16 I##INTERFACE::descriptor(NAME);& && && && && && && &
& & String16 I##INTERFACE::getInterfaceDescriptor() const {& && && && &
& && &&&return I##INTERFACE::& && && && && && && && && && &&&
& & }& && && && && && && && && && && && && && && && && && && && && && &
& & sp&I##INTERFACE& I##INTERFACE::asInterface(const sp&IBinder&& obj)
& & {& && && && && && && && && && && && && && && && && && && && && && &
& && &&&sp&I##INTERFACE&& && && && && && && && && && && && && && &
& && &&&if (obj != NULL) {& && && && && && && && && && && && && && && &
& && && && &intr = static_cast&I##INTERFACE*&(& && && && && && && && &
& && && && && & obj-&queryLocalInterface(& && && && && && && && && && &
& && && && && && && && &I##INTERFACE::descriptor).get());& && && && && &
& && && && &if (intr == NULL) {& && && && && && && && && && && && && &&&
& && && && && & intr = new Bp##INTERFACE(obj);& && && && && && && && &&&
& && && && &}& && && && && && && && && && && && && && && && && && && &&&
& && &&&}& && && && && && && && && && && && && && && && && && && && && &
& && &&&& && && && && && && && && && && && && && && && && &
  在定义自己的类的时候,只需要使用DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE两个接口,并结合类的名称,就可以实现BpInterface中的asInterface()和getInterfaceDescriptor()两个函数。
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:18 编辑
Android的IPC机制Binder的各个部分 2
第二部分 Binder的运作
  2.1 Binder的工作机制
  Service Manager是一个守护进程,它复杂启动各个进程之间的服务,对于相关的两个需要通讯的进程,它们通过调用libutil.so库实现通讯,而真正通讯的截止,是内核空间中的一块共享内存。
  2.2 从应用程序的角度看Binder
  从应用程序的角度看Binder一共有三个方面:
Native 本地:例如BnABC,这是一个需要被继承和实现的类。
Proxy 代理:例如BpABC,这是一个在接口框架中被实现,但是在接口中没有体现的类。
客户端:例如客户端得到一个接口ABC,在调用的时候实际上被调用的是BpABC
本地功能(Bn)部分做的:
  实现BnABC:: BnTransact()
  注册服务:IServiceManager::AddService
代理部分(Bp)做的:
  实现几个功能函数,调用BpABC::remote()-&transact()
客户端做的:
  获得ABC接口,然后调用接口(实际上调用了BpABC,继而通过IPC调用了BnABC,然后调用了具体的功能)
& && & 在程序的实现过程中BnABC和BpABC是双继承了接口ABC。一般来说BpABC是一个实现类,这个实现类不需要在接口中体现,它实际上负责的只是通讯功能,不执行具体的功能;BnABC则是一个接口类,需要一个真正工作的类来继承、实现它,这个类才是真正执行具体功能的类。
  在客户端中,从ISeriviceManager中获得一个ABC的接口,客户端调用这个接口,实际上是在调用BpABC,而BpABC又通过Binder的IPC机制和BnABC通讯,BnABC的实现类在后面执行。
  事实上,服务器的具体实现和客户端是两个不同的进程,如果不考虑进程间通讯的过程,从调用者的角度,似乎客户端在直接调用另外一个进程间的函数——当然这个函数必须是接口ABC中定义的。
  2.3 ISericeManager的作用
  ISericeManager涉及的两个文件是ISericeManager.h和ISericeManager.cpp。这两个文件基本上是ISericeManager。ISericeManager是系统最先被启动的服务。非常值得注意的是:ISericeManager本地功能并没有使现,它实际上由ServiceManager守护进程执行,而用户程序通过调用BpServiceManager来获得其他的服务。
  在ISericeManager.h中定义了一个接口,用于得到默认的ISericeManager:
  sp&IServiceManager& defaultServiceManager();
  这时得到的ISericeManager实际上是一个全局的ISericeManager。
在线时间1282 小时最后登录阅读权限65UID829815注册时间积分19296精华3
隐与之雾 退山之巅 吾乃隐退
, 积分 19296, 距离下一级还需 10704 积分
主题帖子 金币6921 元 智豆3 点
本帖最后由 !隐退! 于
18:19 编辑
Android的IPC机制Binder的各个部分 3
3.1 一个利用接口的具体实现
  PermissionController也是libutils中定义的一个有关权限控制的接口,它一共包含两个文件:IPermissionController.h和IPermissionController.cpp这个结构在所有类的实现中都是类似的。
  头文件IPermissionController.h的主要内容是定义IPermissionController接口和类BnPermissionController:
class IPermissionController : public IInterface
  DECLARE_META_INTERFACE(PermissionController);
  virtual bool& &checkPermission(const String16& permission,int32_t pid, int32_t uid) = 0;
  enum {
  CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
class BnPermissionController : public BnInterface&IPermissionController&
& & virtual status_t& & onTransact( uint32_t code,
& && && && && && && && && && && && &const Parcel& data,
& && && && && && && && && && && && &Parcel* reply,
& && && && && && && && && && && && &uint32_t flags = 0);
  IPermissionController是一个接口类,只有checkPermission()一个纯虚函数。
  BnPermissionController继承了以BnPermissionController实例化模版类BnInterface。因此,BnPermissionController,事实上BnPermissionController双继承了BBinder和IPermissionController。
  实现文件IPermissionController.cpp中,首先实现了一个BpPermissionController。
class BpPermissionController : public BpInterface&IPermissionController&
  BpPermissionController(const sp&IBinder&& impl)
& && &&&: BpInterface&IPermissionController&(impl)
& & virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid)
& && &&&Parcel data,
& && &&&data.writeInterfaceToken(IPermissionController::
& && && && && && && && && && && && && &getInterfaceDescriptor());
& && &&&data.writeString16(permission);
& && &&&data.writeInt32(pid);
& && &&&data.writeInt32(uid);
& && &&&remote()-&transact(CHECK_PERMISSION_TRANSACTION, data, &reply);
& && &&&if (reply.readInt32() != 0) return 0;
& && &&&return reply.readInt32() != 0;
IMPLEMENT_META_INTERFACE(PermissionController, &android.os.IPermissionController&);
  BpPermissionController继承了BpInterface&IPermissionController&,它本身是一个已经实现的类,而且并没有在接口中体现。这个类按照格式写就可以,在实现checkPermission()函数的过程中,使用Parcel作为传输数据的容器,传输中时候transact()函数,其参数需要包含枚举值CHECK_PERMISSION_TRANSACTION。IMPLEMENT_META_INTERFACE用于扶助生成。
  BnPermissionController中实现的onTransact()函数如下所示:
status_t BnPermissionController:: BnTransact(
& & uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
& & switch(code) {
& && &&&case CHECK_PERMISSION_TRANSACTION: {
& && && && &CHECK_INTERFACE(IPermissionController, data, reply);
& && && && &String16 permission = data.readString16();
& && && && &int32_t pid = data.readInt32();
& && && && &int32_t uid = data.readInt32();
& && && && &bool res = checkPermission(permission, pid, uid);
& && && && &reply-&writeInt32(0);
& && && && &reply-&writeInt32(res ? 1 : 0);
& && && && &return NO_ERROR;
& && &&&default:
& && && && &return BBinder:: BnTransact(code, data, reply, flags);
  在onTransact()函数中根据枚举值判断数据使用的方式。注意,由于BnPermissionController也是继承了类IPermissionController,但是纯虚函数checkPermission()依然没有实现。因此这个BnPermissionController类并不能实例化,它其实也还是一个接口,需要一个实现类来继承它,那才是实现具体功能的类。
  3.2 BnABC的实现
  本地服务启动后将形成一个守护进程,具体的本地服务是由一个实现类继承BnABC来实现的,这个服务的名称通常叫做ABC。
  在其中,通常包含了一个instantiate()函数,这个函数一般按照如下的方式实现:
void ABC::instantiate() {
& & defaultServiceManager()-&addService(
& && && && &String16(&XXX.ABC&), new ABC ());
  按照这种方式,通过调用defaultServiceManager()函数,将增加一个名为&XXX.ABC&的服务。
  在这个defaultServiceManager()函数中调用了:
ProcessState::self()-&getContextObject(NULL));
  IPCThreadState* ipc = IPCThreadState::self();
  IPCThreadState::talkWithDriver()
在ProcessState 类建立的过程中调用open_driver()打开驱动程序,在talkWithDriver()的执行过程中。
  3.3 BpABC调用的实现
  BpABC调用的过程主要通过mRemote()-&transact() 来传输数据,mRemote()是BpRefBase的成员,它是一个IBinder。这个调用过程如下所示:
  mRemote()-&transact()
  Process::self()
  IPCThreadState::self()-&transact()
  writeTransactionData()
  waitForResponse()
  talkWithDriver()
  ioctl(fd, BINDER_WRITE_READ, &bwr)
  在IPCThreadState::executeCommand()函数中,实现传输操作。
加智友微信, 原来老司机们都在福利群里!!}

我要回帖

更多关于 解除代持股协议 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信