青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

life02

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  197 隨筆 :: 3 文章 :: 37 評論 :: 0 Trackbacks
http://android.blog.51cto.com/268543/537684
AIDL的作用
    由于每個應用程序都運行在自己的進程空間,并且可以從應用程序UI運行另一個服務進程,而且經常會在不同的進程間傳遞對象。在Android平臺,一 個進程通常不能訪問另一個進程的內存空間,所以要想對話,需要將對象分解成操作系統可以理解的基本單元,并且有序的通過進程邊界。
    通過代碼來實現這個數據傳輸過程是冗長乏味的,Android提供了AIDL工具來處理這項工作。
 
    AIDL (Android Interface Definition Language) 是一種IDL 語言,用于生成可以在Android設備上兩個進程之間進行進程間通信(interprocess communication, IPC)的代碼。如果在一個進程中(例如Activity)要調用另一個進程中(例如Service)對象的操作,就可以使用AIDL生成可序列化的參 數。
    AIDL IPC機制是面向接口的,像COM或Corba一樣,但是更加輕量級。它是使用代理類在客戶端和實現端傳遞數據。
  
選擇AIDL的使用場合
    官方文檔特別提醒我們何時使用AIDL是必要的:只有你允許客戶端從不同的應用程序為了進程間的通信而去訪問你的service,以及想在你的service處理多線程。
 
    如果不需要進行不同應用程序間的并發通信(IPC),you should create your interface by implementing a Binder;或者你想進行IPC,但不需要處理多線程的,則implement your interface using a Messenger。無論如何,在使用AIDL前,必須要理解如何綁定service——bindService。
 
    在設計AIDL接口前,要提醒的是,調用AIDL接口是直接的方法調用的,不是我們所想象的調用是發生在線程里。而調用(call)來自local進程或者remote進程,有什么區別呢?尤其是以下情況(引用原文,不作翻譯了,以免翻譯有誤):
  • Calls made from the local process are executed in the same thread that is making the call. If this is your main UI thread, that thread continues to execute in the AIDL interface. If it is another thread, that is the one that executes your code in the service. Thus, if only local threads are accessing the service, you can completely control which threads are executing in it (but if that is the case, then you shouldn't be using AIDL at all, but should instead create the interface by implementing a Binder).
  • Calls from a remote process are dispatched from a thread pool the platform maintains inside of your own process. You must be prepared for incoming calls from unknown threads, with multiple calls happening at the same time. In other words, an implementation of an AIDL interface must be completely thread-safe.
  • The oneway keyword modifies the behavior of remote calls. When used, a remote call does not block; it simply sends the transaction data and immediately returns. The implementation of the interface eventually receives this as a regular call from the Binder thread pool as a normal remote call. If oneway is used with a local call, there is no impact and the call is still synchronous.

定義AIDL接口
    AIDL接口文件,和普通的接口內容沒有什么特別,只是它的擴展名為.aidl。保存在src目錄下。如果其他應用程序需要IPC,則那些應用程序的src也要帶有這個文件。Android SDK tools就會在gen目錄自動生成一個IBinder接口文件。service必須適當地實現這個IBinder接口。那么客戶端程序就能綁定這個service并在IPC時從IBinder調用方法。
    每個aidl文件只能定義一個接口,而且只能是接口的聲明和方法的聲明。
 
1.創建.aidl文件
     AIDL使用簡單的語法來聲明接口,描述其方法以及方法的參數和返回值。這些參數和返回值可以是任何類型,甚至是其他AIDL生成的接口。
    其中對于Java編程語言的基本數據類型 (int, long, char, boolean等),String和CharSequence,集合接口類型List和Map,不需要import 語句。
    而如果需要在AIDL中使用其他AIDL接口類型,需要import,即使是在相同包結構下。AIDL允許傳遞實現Parcelable接口的類,需要import.
    需要特別注意的是,對于非基本數據類型,也不是String和CharSequence類型的,需要有方向指示,包括in、out和inout,in表示由客戶端設置,out表示由服務端設置,inout是兩者均可設置。
    AIDL只支持接口方法,不能公開static變量。
 
例如 (IMyService.aidl): 
package com.demo;

import com.demo.Person;

interface IMyService {
        void savePersonInfo(in Person person);
        List<Person> getAllPerson();
}
2.實現接口
    創建一個類實現剛才那個aidl的接口:
public class RemoteService extends Service {

        private LinkedList<Person> personList = new LinkedList<Person>();
        
        @Override
        public IBinder onBind(Intent intent) {
                return mBinder;
        }

        private final IMyService.Stub mBinder = new IMyService.Stub(){

                @Override
                public void savePersonInfo(Person person) throws RemoteException {
                        if (person != null){
                                personList.add(person);
                        }
                }

                @Override
                public List<Person> getAllPerson() throws RemoteException {
                        return personList;
                }
        };
}
 
    這里會看到有一個名為IMyService.Stub類,查看aidl文件生成的Java文件源代碼就能發現有這么一段代碼:
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.demo.IMyService
    原來Stub類就是繼承于Binder類,也就是說RemoteService類和普通的Service類沒什么不同,只是所返回的IBinder對象比較特別,是一個實現了AIDL接口的Binder。
 
    接下來就是關于所傳遞的數據Bean——Person類,是一個序列化的類,這里使用Parcelable 接口來序列化,是Android提供的一個比Serializable 效率更高的序列化類。
    Parcelable需要實現三個函數:
    1) void writeToParcel(Parcel dest, int flags) 將需要序列化存儲的數據寫入外部提供的Parcel對象dest。而看了網上的代碼例子,個人猜測,讀取Parcel數據的次序要和這里的write次序一致,否則可能會讀錯數據。具體情況我沒試驗過!
    2) describeContents() 沒搞懂有什么用,反正直接返回0也可以
    3) static final Parcelable.Creator對象CREATOR  這個CREATOR命名是固定的,而它對應的接口有兩個方法:
    createFromParcel(Parcel source) 實現從source創建出JavaBean實例的功能

    newArray(int size) 創建一個類型為T,長度為size的數組,僅一句話(return new T[size])即可。估計本方法是供外部類反序列化本類數組使用。
  
仔細觀察Person類的代碼和上面所說的內容:
public class Person implements Parcelable {

        private String name;
        private String telNumber;
        private int age;

        public Person() {}

        public Person(Parcel pl){
                name = pl.readString();
                telNumber = pl.readString();
                age = pl.readInt();
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

        public String getTelNumber() {
                return telNumber;
        }

        public void setTelNumber(String telNumber) {
                this.telNumber = telNumber;
        }

        public int getAge() {
                return age;
        }

        public void setAge(int age) {
                this.age = age;
        }

        @Override
        public int describeContents() {
                return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
                dest.writeString(name);
                dest.writeString(telNumber);
                dest.writeInt(age);
        }

        public static final Parcelable.Creator<Person> CREATOR = new Parcelable.Creator<Person>() {

                @Override
                public Person createFromParcel(Parcel source) {
                        return new Person(source);
                }

                @Override
                public Person[] newArray(int size) {
                        return new Person[size];
                }

        };
}

然后創建Person.aidl文件,注意這里的parcelable和原來實現的Parcelable 接口,開頭的字母p一個小寫一個大寫:
package com.demo;

parcelable Person;
 
     對于實現AIDL接口,官方還提醒我們:
    1. 調用者是不能保證在主線程執行的,所以從一調用的開始就需要考慮多線程處理,以及確保線程安全;
    2. IPC調用是同步的。如果你知道一個IPC服務需要超過幾毫秒的時間才能完成地話,你應該避免在Activity的主線程中調用。也就是IPC調用會掛起應用程序導致界面失去響應,這種情況應該考慮單獨開啟一個線程來處理。
    3. 拋出的異常是不能返回給調用者(跨進程拋異常處理是不可取的)。
 
3. 客戶端獲取接口
    客戶端如何獲取AIDL接口呢?通過IMyService.Stub.asInterface(service)來得到IMyService對象:
private IMyService mRemoteService;

private ServiceConnection mRemoteConnection = new ServiceConnection() {    
        public void onServiceConnected(ComponentName className, IBinder service) {    
                mRemoteService = IMyService.Stub.asInterface(service);    
        }    

        public void onServiceDisconnected(ComponentName className) {    
                mRemoteService = null;    
        }    
};
 在生成的IMyService.java里面會找到這樣的代碼:
/**
* Cast an IBinder object into an com.demo.IMyService interface,
* generating a proxy if needed.
*/
public static com.demo.IMyService asInterface(android.os.IBinder obj) {...}
 
而service的綁定沒有什么不同:
if (mIsRemoteBound) {
        unbindService(mRemoteConnection);
}else{
        bindService(new Intent("com.demo.IMyService"),
                               mRemoteConnection, Context.BIND_AUTO_CREATE);
}

mIsRemoteBound = !mIsRemoteBound;
 
通過IPC調用/傳遞數據
    客戶端綁定service后就能通過IPC來調用/傳遞數據了,直接調用service對象的接口方法:
addPersonButton.setOnClickListener(
                new View.OnClickListener(){
                        private int index = 0;

                        @Override
                        public void onClick(View view) {
                                Person person = new Person();
                                index = index + 1;
                                person.setName("Person" + index);
                                person.setAge(20);
                                person.setTelNumber("123456"); 
                                try {
                                        mRemoteService.savePersonInfo(person);
                                } catch (RemoteException e) {
                                        e.printStackTrace();
                                } 
                        }
                });

listPersonButton.setOnClickListener(
                new View.OnClickListener(){

                        @Override
                        public void onClick(View view) {
                                List<Person> list = null; 

                                try {
                                        list = mRemoteService.getAllPerson();
                                } catch (RemoteException e) {
                                        e.printStackTrace();
                                } 

                                if (list != null){
                                        StringBuilder text = new StringBuilder();

                                        for(Person person : list){
                                                text.append("\nPerson name:");
                                                text.append(person.getName());
                                                text.append("\n             age :");
                                                text.append(person.getAge());
                                                text.append("\n tel number:");
                                                text.append(person.getTelNumber());
                                        }

                                        inputPersonEdit.setText(text);
                                }else {
                                        Toast.makeText(ServiceActivity.this, "get data error",
                                                        Toast.LENGTH_SHORT).show();
                                }
                        }
                });

 Permission權限
    如果Service在AndroidManifest.xml中聲明了全局的強制的訪問權限,其他引用必須聲明權限才能來start,stop或bind這個service.
     另外,service可以通過權限來保護她的IPC方法調用,通過調用checkCallingPermission(String)方法來確保可以執行這個操作。

 AndroidManifest.xml的Service元素
<service android:name=".RemoteService" android:process=":remote">
        <intent-filter>
                <action android:name="com.demo.IMyService" />
        </intent-filter>
</service>
    這里的android:process=":remote",一開始我沒有添加的,在同一個程序里使用IPC,即同一個程序作為客戶端/服務器端,結果運 行mRemoteService = IMyService.Stub.asInterface(service);時提示空指針異常。觀察了人家的在不同程序里進行IPC的代碼,也是沒有這 個android:process=":remote"的。后來在官方文檔http://androidappdocs.appspot.com/guide/topics/manifest/service-element.html里了解到(留意第二段文字):
android:process
The name of the process where the service is to run. Normally, all components of an application run in the default process created for the application. It has the same name as the application package. The <application> element's process attribute can set a different default for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes.
 
If the name assigned to this attribute begins with a colon (':'), a new process, private to the application, is created when it's needed and the service runs in that process. If the process name begins with a lowercase character, the service will run in a global process of that name, provided that it has permission to do so. This allows components in different applications to share a process, reducing resource usage.
 也就是說android:process=":remote",代表在應用程序里,當需要該service時,會自動創建新的進程。而如果是android:process="remote",沒有“:”分號的,則創建全局進程,不同的應用程序共享該進程。
 
以上內容結合了不少網絡文章,包括來自
posted on 2012-03-06 11:49 life02 閱讀(505) 評論(0)  編輯 收藏 引用 所屬分類: android組件學習
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美99在线视频观看| 娇妻被交换粗又大又硬视频欧美| 久久综合99re88久久爱| 蜜臀av性久久久久蜜臀aⅴ| 欧美理论在线播放| 欧美日韩在线一区| 国产精品一区二区在线观看不卡 | 日韩一区二区福利| 在线性视频日韩欧美| 久久av免费一区| 免费看的黄色欧美网站| 亚洲精选中文字幕| 性做久久久久久久久| 免费黄网站欧美| 一区二区三区高清视频在线观看| 久久久国产一区二区三区| 欧美日韩视频一区二区| 亚洲欧洲一区二区天堂久久| 亚洲一区一卡| 欧美激情一区二区| 先锋影院在线亚洲| 国产精品乱人伦一区二区| 91久久一区二区| 一区二区三区视频在线| 国产亚洲综合性久久久影院| 亚洲视频专区在线| 亚洲国产一区二区在线| 亚洲综合欧美| 久久精品国产精品亚洲精品| 国产精品一区二区在线观看不卡| 久久久久国产精品厨房| 亚洲一区国产视频| 欧美性做爰毛片| 亚洲一区二区免费视频| 一二三区精品福利视频| 影音先锋日韩资源| 美女精品视频一区| 亚洲福利小视频| 久久综合九色99| 午夜精品久久久久久| 夜夜嗨一区二区| 亚洲电影免费观看高清| 国产精品午夜春色av| 欧美在线视频导航| 久久久久99精品国产片| 国产欧美一区二区精品秋霞影院| 香蕉久久夜色精品| 欧美精品色网| 亚洲丝袜av一区| 麻豆av一区二区三区| 久久精品五月婷婷| 久久久在线视频| 欧美在线观看网址综合| 久久久国产成人精品| 欧美天堂亚洲电影院在线播放| 鲁大师影院一区二区三区| 久久久久久香蕉网| 久久成年人视频| 国产精品扒开腿爽爽爽视频| 亚洲国产网站| 亚洲国产高清高潮精品美女| 亚洲高清激情| 亚洲激精日韩激精欧美精品| 亚洲免费电影在线| 久久亚洲精品一区| 一本色道久久综合亚洲精品小说| 久久久7777| 老司机一区二区| 极品少妇一区二区三区| 欧美中文字幕视频在线观看| 性8sex亚洲区入口| 国产精品一级| 欧美在线综合视频| 国产视频欧美视频| 亚洲精品一区二| 国产精品大片wwwwww| 美女日韩欧美| 亚洲国产三级| 美女视频网站黄色亚洲| 欧美激情一区二区| 亚洲深夜福利| 亚洲——在线| 欧美中在线观看| 一区二区三区在线视频免费观看 | 最新中文字幕一区二区三区| 欧美精品手机在线| 日韩午夜激情| 欧美一区免费视频| 精品电影一区| 亚洲春色另类小说| 国产综合视频在线观看| 91久久精品美女高潮| 一区二区三区欧美成人| 久久久天天操| 亚洲精选在线| 欧美中文字幕在线播放| 亚洲国产天堂久久综合| 欧美丝袜一区二区| 欧美在线精品免播放器视频| 黄色成人在线网址| 一区二区三区国产精华| 久久精品国产一区二区电影| 亚洲国产美女精品久久久久∴| 欧美激情亚洲| 性一交一乱一区二区洋洋av| 欧美丰满高潮xxxx喷水动漫| 国产欧美一区二区精品仙草咪| 久久精品免费看| 一区二区动漫| 韩国av一区| 欧美视频在线观看免费| 久久久成人精品| 在线亚洲免费| 欧美激情中文字幕在线| 久久精品免视看| 亚洲图片欧洲图片av| 尤物精品国产第一福利三区| 国产精品国产精品| 女主播福利一区| 性色av一区二区三区| 日韩视频在线免费| 欧美激情一区二区三区在线视频观看| 亚洲一区二区黄色| 亚洲人成网站在线观看播放| 国产一区二区三区精品久久久| 欧美日韩在线直播| 欧美二区在线播放| 欧美sm重口味系列视频在线观看| 在线看一区二区| 另类av导航| 欧美中文字幕在线视频| 亚洲在线观看免费| 国产精品99久久久久久有的能看| 亚洲电影免费在线观看| 久久久综合精品| 亚洲国产精品成人综合色在线婷婷| 国产精品欧美在线| 欧美日韩一区二区三区免费| 欧美成人综合一区| 麻豆av一区二区三区| 久久伊伊香蕉| 久久久久久久久久久久久久一区 | 亚洲精品自在在线观看| 欧美激情一区二区三区在线| 欧美成人免费播放| 免费永久网站黄欧美| 蜜臀av性久久久久蜜臀aⅴ| 久久青草欧美一区二区三区| 久久精品女人| 黑人操亚洲美女惩罚| 韩国av一区| 一区二区亚洲精品| 亚洲高清在线视频| 亚洲久久一区二区| 欧美电影免费观看| 欧美精品观看| 欧美视频一区在线| 国产精品成人国产乱一区| 欧美亚洲成人精品| 国产精品一区二区在线观看不卡| 国产日韩欧美一区| 精品成人在线视频| 亚洲人成人一区二区三区| 99精品免费视频| 国产日韩精品电影| 亚洲欧美综合国产精品一区| 欧美激情第3页| 亚洲欧洲日本在线| 亚洲天堂网在线观看| 久久一区二区三区超碰国产精品| 亚洲视频免费| 亚欧成人精品| 欧美91精品| 日韩亚洲欧美成人一区| 亚洲欧美日韩网| 久久一区二区三区四区| 亚洲国产精品ⅴa在线观看| 99国内精品| 亚洲电影免费观看高清完整版| 亚洲欧洲一区二区在线播放 | 久久视频在线视频| 欧美激情视频一区二区三区免费| 亚洲精选视频免费看| 欧美专区中文字幕| 欧美日韩高清区| 欧美成人一区二区三区| 国产精品美女久久久| 亚洲国产老妈| 欧美一区日韩一区| 亚洲日本欧美日韩高观看| 免费久久精品视频| 中文一区二区在线观看| 裸体一区二区三区| 国产美女高潮久久白浆| 亚洲精品免费电影| 一本色道久久综合亚洲精品小说| 久久国产一区二区| 99re66热这里只有精品4| 久久久久久亚洲综合影院红桃| 欧美日韩国产专区|