Google Developer Day 2011 の参加のためのクイズで、AIDLでサービスへアクセスしてコードを取得してくださいという問題があったので、AIDLについて勉強してみました。
ActivityとServiceの間の通信方法です。
こちらの記事を非常に参考にさせて頂きました。ありがとうございます。
手順は下記です。
1. AIDLファイルにIPCのインターフェースを記述
2. Serviceにインターフェースを実装
3. ActivityからServiceへアクセス
4. Manifest.xmlにServiceを宣言
<手順1>
インターフェースを記述します。
Activityのあるところと同じ階層で、新規ファイルでFileを追加し、拡張子をaidlで保存します。今回のaidlはこのような感じです。
既に存在するActivityと同じ名前で、……Service.javaでファイルを追加します。
package com.google.android.apps.gddquiz;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.google.android.apps.gddquiz.IQuizService;;
public class Gdd2011Service extends Service {
@Override
public IBinder onBind(Intent intent) {
System.out.println("Service::onBind");
return quizService;
//return null;
}
private IQuizService.Stub quizService = new IQuizService.Stub(){
public String getCode() throws RemoteException {
System.out.println("test!!!!!");
return getCode();
}
};
}
こんな感じです。Service.onBindをオーバーライドしてインターフェースを実装したクラスインスタンスを返します。
今のところファイル構成はこのような感じです。
<手順3>
ActivityからServiceにアクセスします。
……Activity.javaを開きます。
package com.google.android.apps.gddquiz;
import com.google.android.apps.gddquiz.IQuizService;
import android.app.Activity;
import android.os.Bundle;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.widget.TextView;
public class Gdd2011Activity extends Activity {
private IQuizService quizService;
private TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = new TextView(this);
Intent intent = new Intent(IQuizService.class.getName());
bindService(intent, _serviceConnection, BIND_AUTO_CREATE);
/* ここで実行してましたが、起動できないようだったので、Connection後取得するように☆印の下記に追加しました。
try {
String code = quizService.getCode();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
private ServiceConnection _serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("onServiceConnected!!");
quizService = IQuizService.Stub.asInterface(service);
// ☆ ここに移動
try {
String code = quizService.getCode();
tv.setText(code);
setContentView(tv);
} catch (RemoteException e) {
System.out.println("Connected false!!");
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName name) {
quizService = null;
}
};
}
Intent intent = new Intent(IQuizService.class.getName());
でサービスのインテントを作成し、bindServiceより、アクセスします。
<手順4>
Manifestにサービス追加
ActivityとServiceの間の通信方法です。
こちらの記事を非常に参考にさせて頂きました。ありがとうございます。
手順は下記です。
1. AIDLファイルにIPCのインターフェースを記述
2. Serviceにインターフェースを実装
3. ActivityからServiceへアクセス
4. Manifest.xmlにServiceを宣言
<手順1>
インターフェースを記述します。
Activityのあるところと同じ階層で、新規ファイルでFileを追加し、拡張子をaidlで保存します。今回のaidlはこのような感じです。
package com.google.android.apps.gddquiz;
interface IQuizService {
String getCode();
}
ファイルを追加し保存すると、gen以下にR.javaと同じ階層に保存したファイル名と同じ名前で、.javaファイルが自動生成されます。
※packeageのパスがあっているかどうか確認してください。
<手順2>
次に、Serviceにインターフェースを実装します。
既に存在するActivityと同じ名前で、……Service.javaでファイルを追加します。
package com.google.android.apps.gddquiz;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import com.google.android.apps.gddquiz.IQuizService;;
public class Gdd2011Service extends Service {
@Override
public IBinder onBind(Intent intent) {
System.out.println("Service::onBind");
return quizService;
//return null;
}
private IQuizService.Stub quizService = new IQuizService.Stub(){
public String getCode() throws RemoteException {
System.out.println("test!!!!!");
return getCode();
}
};
}
こんな感じです。Service.onBindをオーバーライドしてインターフェースを実装したクラスインスタンスを返します。
今のところファイル構成はこのような感じです。
<手順3>
ActivityからServiceにアクセスします。
……Activity.javaを開きます。
package com.google.android.apps.gddquiz;
import com.google.android.apps.gddquiz.IQuizService;
import android.app.Activity;
import android.os.Bundle;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.widget.TextView;
public class Gdd2011Activity extends Activity {
private IQuizService quizService;
private TextView tv;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
tv = new TextView(this);
Intent intent = new Intent(IQuizService.class.getName());
bindService(intent, _serviceConnection, BIND_AUTO_CREATE);
/* ここで実行してましたが、起動できないようだったので、Connection後取得するように☆印の下記に追加しました。
try {
String code = quizService.getCode();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
*/
}
private ServiceConnection _serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) {
System.out.println("onServiceConnected!!");
quizService = IQuizService.Stub.asInterface(service);
// ☆ ここに移動
try {
String code = quizService.getCode();
tv.setText(code);
setContentView(tv);
} catch (RemoteException e) {
System.out.println("Connected false!!");
e.printStackTrace();
}
}
public void onServiceDisconnected(ComponentName name) {
quizService = null;
}
};
}
Intent intent = new Intent(IQuizService.class.getName());
でサービスのインテントを作成し、bindServiceより、アクセスします。
<手順4>
Manifestにサービス追加
<service android:name=".Gdd2011Service"android:label="@string/app_name"android:process=":remote"><intent-filter><action android:name="com.google.android.apps.gddquiz.IQuizService" /></intent-filter></service>
これをActivityタグの後に追加します。
以上です。
間違っていたり、もっといいやりかたがあったら教えて下さい。
よろしくお願いしますー