Androidサービスのサービス——AIDLプロセス間通信について

15927 ワード

原文:
http://www.cnblogs.com/zhangdongzi/archive/2012/01/09/2317197.html
前節では、AIDLに関するリモート・サービスについて説明しました.
はい、古いルールです.まず基礎知識をください.
一.基礎知識
AIDLの役割
Androidプラットフォームでは、各アプリケーションAppが独自のプロセススペースで実行されます.通常、1つのプロセスは別のプロセスのメモリ空間にアクセスできません(1つのアプリケーションは別のアプリケーションにアクセスできません)、コミュニケーションをとるには、オブジェクトをオペレーティングシステムが理解できる基本ユニットに分解する必要があります.AndroidはAIDLを提供して処理します.
 
    
AIDL(Android Interface Definition Language)は、Androidデバイス上の2つのプロセス間でプロセス間通信(interprocess communication,IPC)が可能なコードを生成するIDL言語である.あるプロセス(Activityなど)で別のプロセス(Serviceなど)オブジェクトのアクションを呼び出す場合は、AIDLを使用してシーケンス化可能なパラメータを生成できます.言い換えれば、私のこのアプリのactivityは、他のアプリのServiceを呼び出す必要があります.
.もちろん、同じAppアプリケーションのactivityとserviceも異なるプロセス間で使用できます.これにより、サービス構成でandroid:process=":remote"を設定できます.
AIDLの使用
公式ドキュメントでは、AIDLをいつ使用するかを特に注意しています.クライアントが異なるアプリケーションからプロセス間の通信のためにサービスにアクセスすることを許可し、サービスでマルチスレッドを処理したい場合だけです.△あまりにも硬いので、異なるプロセスのコンポーネントを呼び出しましょう.
ではAIDLはどうやって作りますか?次の手順
1:作成.aidlファイル.新しいファイルを作成し、aidlは接尾辞として保存され、このファイルにはインタフェースとメソッドが記述されています.これは通常javaインタフェース宣言と同じで、複雑なタイプのオブジェクトが同じパッケージ内にあってもimport複雑なタイプを表示するのとは異なります.Java基本データ型(int,long,char,booleanなど)、StringとCharSequence、集合インタフェースタイプListとMap、importは不要です.
例:
package com.dongzi;interface IStockQuoteService{  double getPrice(String ticker);}
2:AIDLファイルを作成したら、プロジェクトをリフレッシュするとgenパッケージの下に、対応するパッケージの下にAIDLファイルと同じjavaファイルが表示されます.次のようになります.

View Code
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: D:\\mywordspace\\MyPhone\\src\\com\\dongzi\\IStockQuoteService.aidl
*/
package com.dongzi;

public interface IStockQuoteService extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements com.dongzi.IStockQuoteService {
private static final java.lang.String DESCRIPTOR = "com.dongzi.IStockQuoteService";

/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}

/**
* Cast an IBinder object into an com.dongzi.IStockQuoteService
* interface, generating a proxy if needed.
*/
public static com.dongzi.IStockQuoteService asInterface(android.os.IBinder obj) {
if ((obj == null)) {
return null;
}
android.os.IInterface iin = (android.os.IInterface) obj.queryLocalInterface(DESCRIPTOR);
if (((iin != null) && (iin instanceof com.dongzi.IStockQuoteService))) {
return ((com.dongzi.IStockQuoteService) iin);
}
return new com.dongzi.IStockQuoteService.Stub.Proxy(obj);
}

public android.os.IBinder asBinder() {
return this;
}

@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
throws android.os.RemoteException {
switch (code) {
case INTERFACE_TRANSACTION: {
reply.writeString(DESCRIPTOR);
return true;
}
case TRANSACTION_getPrice: {
data.enforceInterface(DESCRIPTOR);
java.lang.String _arg0;
_arg0 = data.readString();
double _result = this.getPrice(_arg0);
reply.writeNoException();
reply.writeDouble(_result);
return true;
}
}
return super.onTransact(code, data, reply, flags);
}

private static class Proxy implements com.dongzi.IStockQuoteService {
private android.os.IBinder mRemote;

Proxy(android.os.IBinder remote) {
mRemote = remote;
}

public android.os.IBinder asBinder() {
return mRemote;
}

public java.lang.String getInterfaceDescriptor() {
return DESCRIPTOR;
}

public double getPrice(java.lang.String ticker) throws android.os.RemoteException {
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
double _result;
try {
_data.writeInterfaceToken(DESCRIPTOR);
_data.writeString(ticker);
mRemote.transact(Stub.TRANSACTION_getPrice, _data, _reply, 0);
_reply.readException();
_result = _reply.readDouble();
}
finally {
_reply.recycle();
_data.recycle();
}
return _result;
}
}

static final int TRANSACTION_getPrice = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
}

public double getPrice(java.lang.String ticker) throws android.os.RemoteException;
}


AIDLツールは自動的にそんなに多くのコードを生成して、実は私たちは3つを知るだけで十分です.
public static abstract class Stub extends android.os.Binder implements com.dongzi.IStockQuoteService静的抽象内部クラスStub
private static class Proxy implements com.dongzi.IStockQuoteService AIDLサービスエージェントクラス
public double getPrice(java.lang.String ticker) throws android.os.RemoteException;AIDLが公表したインタフェースは,我々が定義したインタフェースの方法である.
3:AIDLファイルを他のクライアントアプリケーションに保存し、これをサービス側とします.もちろん、このアプリケーションをクライアントおよびサービス側として便利に使用することもできます.根本的な違いは、呼び出し元と呼び出し元を異なるプロセスにするために、android:process=「:remote」をサービスに追加すればよいことです.アプリケーションクライアント呼び出しの再確立を省く.
4:AIDLは契約を定義してください.ここではサービスを提供するためにサービスが必要です.そこでサービスを立ち上げました
二.実戦
いくつかの基礎知識を知ってから、コードを始めましょう.株価照会やGPS測位のサービスを提供するプロセスで他のアプリケーションのサービスを呼び出す必要があると仮定します.
そしてクラスを定義して、私たちのAIDLが生成したStub内部クラスを継承して、そして私たちのAIDL定義の方法を実現します
コードは次のとおりです.

View Code
package com.dongzi;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service {
static final String TAG="MyService";

// MyServiceImpl AIDL ,
// AIDL
private class MyServiceImpl extends IStockQuoteService.Stub{

@Override
public double getPrice(String ticker) throws RemoteException {
Log.e(TAG, "getPrice");
return 10.5;
}

}

@Override
public IBinder onBind(Intent arg0) {
// AIDL
return new MyServiceImpl();
}


@Override
public void onDestroy(){
Log.e(TAG, "Release MyService");
super.onDestroy();
}
}


他のプロセス呼び出しのためにonBindメソッドでAIDLインタフェース実装オブジェクトを返す必要があります.
もちろん、今はAIDLもサービスも定義されています.mainfestが必要です.xmlでの設定
 <service android:name=".MyService"
android:process=":remote"
>
<intent-filter>
<action android:name="com.dongzi.IStockQuoteService"/>
</intent-filter>
</service>


クライアント・サービス・エンドが同じAppでandroid:process=「:remote」は、アプリケーションに代表され、サービスが必要な場合に自動的に新しいプロセスが作成されます.一方、android:process=「remote」で、「:」セミコロンがない場合は、グローバルプロセスが作成され、異なるアプリケーションがプロセスを共有します.では、クライアントがサービスを呼び出します.コードは次のとおりです.

View Code
package com.dongzi;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MYyActivity extends Activity {
static final String TAG="MYyActivity";
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btnCall=(Button)findViewById(R.id.btnCall);
if(btnCall!=null)
btnCall.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
//
bindMyService();
}
});
}

IStockQuoteService iService=null;
private ServiceConnection conn=new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// AIDL , AIDL
iService=IStockQuoteService.Stub.asInterface(service);
double value=0.0;
try {
value=iService.getPrice("");
}
catch (RemoteException e) {
Log.e(TAG," !");
e.printStackTrace();
}
Log.e(TAG, " :"+value);
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, " Service");
}
};

private void bindMyService(){
// Intent intent=new Intent("com.dongzi.IStockQuoteService");
Intent intent=new Intent(this,MyService.class);
startService(intent);

bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
}


ボタンクリック時にサービスを起動し、このサービスをバインドします.サービスに接続すると、AIDLで定義されたメソッドを呼び出すと、次のように印刷されます.
Android服务之Service——关于AIDL进程间通信_第1张图片
プロジェクト構造は次のとおりです.
Android服务之Service——关于AIDL进程间通信_第2张图片