AndroidリモートインタフェースのAIDL——Parcelable、in、out、inoutの簡単な例


AIDL簡略化
Androidでのデータ転送、メソッド呼び出しなどは、Activity-AがActivity-Bに渡されるなど、アプリケーション内のActivity間に集中することが一般的です.
このようなデータ転送、方法などは、1つのアプリケーション間で呼び出され、すなわち1つのプロセス内で呼び出される.もし私たちが異なるプロセス間でデータを伝えるなら、私たちはどうすればいいですか?同じプロセス間ではなく、メモリを共有することはできません.Androidはプロセス間のデータ共有を実現するために、AIDLメカニズム(Androidリモートインタフェース定義言語)を提供しています.(AIDL:Android Interface definition language).
AIDLの原理と原理分析は、ネット上の他の解釈を参考にすることができる.
以下では、主にAIDLの様々な修飾子(in、out、inout)およびクラスシーケンス化Parcelableの使用例について説明する(ネット上の原理は多く説明されているが、out、inoutの例はめったに見られない).
AIDLの実現
AIDLの適用シーンは、一般に2つのプロセスがあり、1つのプロセスは方法を提供し、1つのプロセスは方法を呼び出す.
我々は、メソッドを提供するプロセスをサービス側として定義し、メソッドを呼び出すプロセスをClientとして定義することに慣れています.これは、我々がよく言うAIDLサービス側とAIDLクライアントです.
AIDLのデータ転送サポートタイプには特別な要求があり、すべてのデータタイプが従来のように転送できるわけではありません.
サポートデータ型は次のとおりです:1.Javaのオリジナルタイプ2.StringとCharSequence 3.ListとMap、ListとMapオブジェクトの要素はAIDLがサポートするデータ型でなければならない.以上の3つのタイプはインポート(import)4を必要としない.AIDLが自動的に生成するインタフェースはインポート(import)5が必要である.実現するos.Parcelableインタフェースのクラスインポート(import)が必要です. 
次に、AIDLのサービス側とクライアントをどのように提供するかを示します.
ここでは、in、out、inout修飾子、Parcelableの使用に重点を置きます!よくあるのはin、Parcelable、少ないout、inoutです.
このいくつかの修飾子は、以下のように理解できます.
in:クライアントのパラメータ入力;
out:サービス側のパラメータ入力;
inout:これは入出力パラメータと呼ばれ、クライアントは入力、サービス側も入力できます.クライアントがサービス側にパラメータを入力すると、サービス側もそのパラメータを修正するなどして、最後にクライアントで得られるのはサービス側出力のパラメータです.
AIDLのサービス側(サービス側)実現
一般的なアプローチ:
1、AIDLインタフェースを定義し、そのインタフェースに方法を書く.
2、方法中のパラメータ修飾子はin、out、inoutであってもよく、Parcelableインタフェースを実現する必要があるカスタムクラスもある.
3、このインタフェースを実現する;
4.サービス側インタフェースメソッドにアクセスするための、クライアントに開放されたフラグ.
上記の3つの手順で、サンプルコードを書きます.
1、AIDLインタフェースを定義する:
IBaseという名前のファイルを新規作成します.aidl、内容:
package com.example.aidl;
import com.example.aidl.UserInfo;//    
interface IBase
{
     int    add(int i,int j);
     String getUserInfo(in UserInfo userinfo);
     void   getaList(out String[] list);  
     void   setaList(in String[] list);
     void   gettList(inout String[] list);
}
の上のインタフェースでの方法について,種々の修飾子およびParcelableを実証した.
ここで注意すべき点は、UserInfoクラスと私たちが定義したインタフェースは同じパッケージの下にあるが、ファイルヘッダにimportクラスがあることです.
Parcelableの使用は、まずこのUserInfoのParcelableインタフェース実装を実装し、次に参照します.
package com.example.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class UserInfo implements Parcelable{

	
	private String name;
	private String adress;
	private int  age;
	
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the adress
	 */
	public String getAdress() {
		return adress;
	}

	/**
	 * @param adress the adress to set
	 */
	public void setAdress(String adress) {
		this.adress = adress;
	}

	/**
	 * @return the age
	 */
	public int getAge() {
		return age;
	}

	/**
	 * @param age the age to set
	 */
	public void setAge(int age) {
		this.age = age;
	}

	@Override
	public int describeContents() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void writeToParcel(Parcel dest, int flags) {
		// TODO Auto-generated method stub
		dest.writeString(name);
		dest.writeString(adress);
		dest.writeInt(age);
	}
   
	public static final Parcelable.Creator CREATOR=new Creator() {

		@Override
		public UserInfo createFromParcel(Parcel source) {
			// TODO Auto-generated method stub
			UserInfo userInfo=new UserInfo();
			userInfo.setName(source.readString());
			userInfo.setAdress(source.readString());
			userInfo.setAge(source.readInt());
			return userInfo;
		}

		@Override
		public UserInfo[] newArray(int size) {
			// TODO Auto-generated method stub
			return new UserInfo[size];
		}
	};
}
このカスタムクラスを宣言します.
同じパッケージの下にUserInfoを作成します.aidlファイル、内容は以下の通りです.
package com.example.aidl;

parcelable UserInfo;

以上のように、カスタムクラスを使用するには、いくつかの手順が必要です.
(1)Parcelableインタフェースを実現する.具体的なプロセスは以下の通りである.http://blog.csdn.net/yangzhaomuma/article/details/50452651;
(2)同じパッケージ名でクラス同名のAIDLファイルを作成する.
(3)このクラスを使用する場合は,ファイルヘッダで参照(import)する必要がある.
2、インタフェースの実現方法:
Javaファイルを新規作成します.名前はAIDLServicesです.JAva、このファイルはAIDLを実現するインタフェースです.内容は次のとおりです.
package com.example.aidl_server_csdn;


import com.example.aidl.IBase;
import com.example.aidl.UserInfo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;

public class AIDLService extends Service{

	String info="";
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return stub;
	}

	private IBase.Stub stub=new IBase.Stub() {

		/**
		 *          
		 */
		@Override
		public int add(int i, int j) throws RemoteException {
			// TODO Auto-generated method stub
			return i+j;
		}
		/**
		 * Parcelable userinfo     
		 */
		@Override
		public String getUserInfo(UserInfo userinfo) throws RemoteException {
			// TODO Auto-generated method stub
			String resultString="name:"+userinfo.getName()+" "+"adress:"+userinfo.getAdress()+" "+"age:"+userinfo.getAge();
			return resultString;
		}
		/**
		 * out       
		 *        
		 */
		@Override
		public void getaList(String[] list) throws RemoteException {
			// TODO Auto-generated method stub
			list[0]="       :"+info;
		}

		/**
		 * inout         
		 */
		@Override
		public void gettList(String[] list) throws RemoteException {
			// TODO Auto-generated method stub
			String totalString="";
			/**
			 *          
			 */
			String receviceFromClientString="";
			for(int i=0;i0)
				info=list[0];
		}
		
	};
}

3.クライアントアクセス用のフラグを開く
よく使われる方法はAndroidManifestです.xmlでは、次の定義を行います.
 
        
            
             
                
            
    
フィルタ値を設定しました:com.service.use,クライアントはこれによりサービス側にアクセスできる.
これで、サービス側のコードが書き終わりました.サービス側がandroidシステムで動作すると、サービスがインストールされます.apkを実行します.
AIDLクライアント(Client側)の実現
サービス側はすでに実現していますが、クライアントはどのように呼び出しますか?
我々の素朴な考え方では,サービス側のインスタンスを取得し,このインスタンスで対応する方法を呼び出すべきである.AIDLもそう思います.しかし、AIDLのやり方は少し特別です.
1、サービス側のAIDLインタフェースとParcelableクラスをサービス側までコピーする(慣習的には、AIDLのパッケージ全体をクライアントにコピーする).
2、サービス側を接続する;
3、サービス側のインタフェース実装の例を取得する.
4、呼び出し方法;
私たちもこの手順に従ってクライアントを実現します.
1、AIDLパッケージ全体をクライアントにコピーする
これをコピーして、貼り付けてください.
2、接続サービス端
/**
	 *   AIDL
	 */
	public void Connect()
	{
		bindService(new Intent("com.service.use"), serviceConnection, Context.BIND_AUTO_CREATE);
	}
	/**
	 *      
	 */
	ServiceConnection serviceConnection=new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			iBase=null;
			Toast.makeText(MainActivity.this, "    ", Toast.LENGTH_SHORT).show();
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			iBase=IBase.Stub.asInterface(service);
			Toast.makeText(MainActivity.this, "    ", Toast.LENGTH_SHORT).show();
		}
	};
	

3、サービス側の実例を取得する
実は、これは一般的に接続サービス側が成功したとき、すでにやっていました.上のコードのiBase=IBaseのようです.Stub.asInterface(service);
4、呼び出し方法
前のステップでiBaseインスタンスを取得し、メソッドを呼び出すときに、次の方法を使用しました.
 iBase.add(7, 8);
iBase.setaList(new String[]{"戦国剣"});
など.
次に、クライアント呼び出しのすべてのコードを貼り付けます.
package com.example.aidl_csdn;

import com.example.aidl.IBase;
import com.example.aidl.UserInfo;

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

public class MainActivity extends Activity implements OnClickListener{

	IBase iBase;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		Button btn=(Button)findViewById(R.id.btn);
		btn.setOnClickListener(this);
		Button btn1=(Button)findViewById(R.id.btn1);
		btn1.setOnClickListener(this);
		Button btn2=(Button)findViewById(R.id.btn2);
		btn2.setOnClickListener(this);
		Button btn3=(Button)findViewById(R.id.btn3);
		btn3.setOnClickListener(this);
		Button btn4=(Button)findViewById(R.id.btn4);
		btn4.setOnClickListener(this);
		Button btn5=(Button)findViewById(R.id.btn5);
		btn5.setOnClickListener(this);
	}

	/**
	 *   AIDL
	 */
	public void Connect()
	{
		bindService(new Intent("com.service.use"), serviceConnection, Context.BIND_AUTO_CREATE);
	}
	/**
	 *      
	 */
	ServiceConnection serviceConnection=new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			iBase=null;
			Toast.makeText(MainActivity.this, "    ", Toast.LENGTH_SHORT).show();
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			iBase=IBase.Stub.asInterface(service);
			Toast.makeText(MainActivity.this, "    ", Toast.LENGTH_SHORT).show();
		}
	};
	
	/**
	 *       
	 * @return
	 * @throws RemoteException
	 */
	public  int  sum() {
		if(iBase!=null)
		{
			int result=0;
			try {
				result = iBase.add(7, 8);
				Toast.makeText(getApplicationContext(), "        :"+result, Toast.LENGTH_SHORT).show();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return result;
		}
		return 0;
	}
	/**
	 * in       
	 */
	public void setaList()
	{
		if(iBase!=null)
		{
			try {
				iBase.setaList(new String[]{"   "});
				Toast.makeText(getApplicationContext(), "  '   '    ", Toast.LENGTH_SHORT).show();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	/**
	 * out        
	 */
	public void getaList()
	{
		if(iBase!=null)
		{
			String[] list =new String[1];
			try {
				iBase.getaList(list);
				Toast.makeText(getApplicationContext(), "       :"+list[0], Toast.LENGTH_SHORT).show();
			} catch (RemoteException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	/**
	 * Parcelable    
	 */
	public void ParcelableUse()
	{
		if(iBase==null)
			return;
		UserInfo userInfo=new UserInfo();
		userInfo.setName("   ");
		userInfo.setAdress("  ");
		userInfo.setAge(18);
		 try {
			 String resultString=iBase.getUserInfo(userInfo);
			Toast.makeText(getApplicationContext(), "       :"+resultString, Toast.LENGTH_SHORT).show();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * inout       
	 */
	public void inoutUse()
	{
		if(iBase==null)
			return;
		try {
			String[] inStrings={"inout in   "};
			iBase.gettList(inStrings);
			Toast.makeText(getApplicationContext(), "inout       :"+inStrings[0], Toast.LENGTH_SHORT).show();
			
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		switch (v.getId()) {
		case R.id.btn:
		Connect();
			break;
		case R.id.btn1:
			sum();
			break;
		case R.id.btn2:
			ParcelableUse();
			break;
		case R.id.btn3:
			setaList();
			break;
		case R.id.btn4:
			getaList();
			break;
		case R.id.btn5:
			inoutUse();
			break;

		default:
			break;
		}
	}

}

これで、クライアントの実装も完了しました.実行すると、目的の効果が見えます.
注意情報これは簡単なAIDLインスタンスであり、主にAIDLにおける様々な修飾子の使用とカスタムクラスの伝達を説明するためである.AIDLでは,我々がよく用いている方法とは異なり,これらのものは,この例の共有がAIDLメカニズムの理解に役立つことを望んでいる.
ソースコード
ソースアドレス:http://download.csdn.net/detail/yangzhaomuma/9416663