更新:
プロジェクトツリーを右クリックして、IMyAidlInterface.aidlという新しいAIDLファイルを追加します。
package com.test.aidlsample;
import com.test.aidlsample.MyData;
interface IMyAidlInterface {
List<MyData> getData(long id);
}
オブジェクトをクライアントに返す必要がある場合は、オブジェクトをパーセル可能として宣言および定義し、aidlファイルにもインポートする必要があります。他のaidlファイルの横にあるMyData.aidlは次のとおりです。
package com.test.aidlsample;
// Declare MyData so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable MyData;
これは、javaフォルダー内のMyData.javaです。
public class MyData implements Parcelable {
private long productId;
private String productName;
private long productValue;
public MyData(long productId, String productName, long productValue) {
this.productId = productId;
this.productName = productName;
this.productValue = productValue;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.productId);
dest.writeString(this.productName);
dest.writeLong(this.productValue);
}
protected MyData(Parcel in) {
this.productId = in.readLong();
this.productName = in.readString();
this.productValue = in.readLong();
}
public static final Parcelable.Creator<MyData> CREATOR = new Parcelable.Creator<MyData>() {
@Override
public MyData createFromParcel(Parcel source) {
return new MyData(source);
}
@Override
public MyData[] newArray(int size) {
return new MyData[size];
}
};
}
次に、プロジェクトをビルドして、スタブクラスがビルドされるようにします。ビルドが成功したら、サービスを続行します。
public class SdkService extends Service {
private IMyAidlInterface.Stub binder = new IMyAidlInterface.Stub() {
@Override
public List<MyData> getData(long id) throws RemoteException {
//TODO: get data from db by id;
List<MyData> data = new ArrayList<>();
MyData aData = new MyData(1L, "productName", 100L);
data.add(aData);
return data;
}
};
@Nullable
@Override
public IBinder onBind(Intent intent) {
return binder;
}
}
そして、sdkマニフェストにサービスを追加します。次のように、クライアントへの依存関係としてsdkを追加する場合:implementation project(':sdk')
AIDLファイルをクライアントに追加する必要はありません。そうでない場合は、それらを追加してクライアントアプリケーションを構築する必要があります。現在、クライアントアクティビティを実装するためだけに残っています。
public class MainActivity extends AppCompatActivity {
IMyAidlInterface mService;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
IBinder service) {
// This is called when the connection with the service has been
// established, giving us the service object we can use to
// interact with the service. We are communicating with our
// service through an IDL interface, so get a client-side
// representation of that from the raw service object.
mService = IMyAidlInterface.Stub.asInterface(service);
try {
List<MyData> data = mService.getData(1L);
updateUi(data);
} catch (RemoteException e) {
// In this case the service has crashed before we could even
// do anything with it; we can count on soon being
// disconnected (and then reconnected if it can be restarted)
// so there is no need to do anything here.
}
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
}
};
private void updateUi(List<MyData> data) {
//TODO: Update UI here
}
@Override
protected void onResume() {
if (mService == null) {
Intent serviceIntent = new Intent();
//CAREFUL: serviceIntent.setComponent(new ComponentName("your.client.package", "your.sdk.service.path"));
serviceIntent.setComponent(new ComponentName("com.test.sampleclient", "com.test.aidlsample.SdkService"));
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
} else {
try {
updateUi(mService.getData(1L));
} catch (RemoteException e) {
e.printStackTrace();
}
}
super.onResume();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
クライアントアクティビティが可視化されるたびに、SDKサービスからデータを取得します。このテンプレート上にロジックを構築するだけです。SDKアクティビティでは、データをデータベースに保存し、サービスではデータベースからクエリを実行します。このサンプルでは、単純なパラメーターを使用しました。
私はあなたのSDKがクライアントアプリのライブラリであると仮定しました。そうでない場合は、おそらくいくつかの小さな変更を行う必要があります。そして、前に述べたように、ここで詳細を見つけることができます:Androidインターフェース定義言語(AIDL)。この件に関するSOには、サンプルがたくさんあり、さらに多くのQ / Aがあります。幸運を。
オリジナル: SDKアクティビティが前面にあるため、現在表示されていないアクティビティからコールバックを取得する必要がありますか?これを行うには、SDKのデータベースを作成し、データベースにデータを永続化し、開始アクティビティでAIDLを介してデータを取得します。
SdkService sdkService;
CallbackData callbackData
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
sdkService = SdkService.Stub.asInterface(service);
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "Service has unexpectedly disconnected");
sdkService = null;
}
};
onCreateで:
Intent i = new Intent()
i.setClassName("your.sdk.packageName", "your.sdk.service.path.and.name");
bindService(i, mConnection, Context.BIND_AUTO_CREATE);
そして必要なときはいつでも:
if(sdkService != null){
callbackData = sdkService.getCallbacks();
updateUI();
}
バインダーの取得は非同期ジョブであることに注意してください。bindServiceを呼び出した直後にsdkService.getCallbackDataを呼び出すと、NullPointerExceptionが発生します。したがって、getCallbacksとupdateUIをonServiceConnected内に移動し、onResumeでbindServiceを呼び出すと、アクティビティが表示されるたびにCallbackDataがあるかどうかを確認して、UIなどを更新できます。