Activity中使用AIDL让Service与Activity通信
简易计算器,默认执行1+1的计算,点击go按钮执行计算,先看效果图,如下
首先建立一个ICallback.aidl文件,作为Activity中的回调方法
// My AIDL file, named SomeClass.aidlpackage com.zhang.test.service;// See the list above for which classes need// import statements (hint--most of them)// Declare the interface.interface ICallback {// Methods can take 0 or more parameters, and// return a value or void.// Methods can even take other AIDL-defined parameters.//BankAccount createAccount(in String name, int startingDeposit, in IAtmService atmService);// All non-Java primitive parameters (e.g., int, bool, etc) require// a directional tag indicating which way the data will go. Available// values are in, out, inout. (Primitives are in by default, and cannot be otherwise).// Limit the direction to what is truly needed, because marshalling parameters// is expensive.void showResult(int result);}package com.zhang.test.service;import com.zhang.test.service.ICallback;interface IService {void registerCallback(ICallback cb);void unregisterCallback(ICallback cb);}package com.zhang.test.service;import android.app.Service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.Handler;import android.os.IBinder;import android.os.Message;import android.os.RemoteCallbackList;import android.os.RemoteException;import android.util.Log;public class CalculateService extends Service {private static final String TAG = "MainService";public static final String ACTION_CALCUlATE = "action_calculate";private RemoteCallbackList<ICallback> mCallbacks = new RemoteCallbackList<ICallback>();private IService.Stub mBinder = new IService.Stub() {@Overridepublic void unregisterCallback(ICallback cb) {if (cb != null) {mCallbacks.unregister(cb);}}@Overridepublic void registerCallback(ICallback cb) {if (cb != null) {mCallbacks.register(cb);}}}; //这里的BroadcastReceiver实现了Activity主动与Service通信private BroadcastReceiver receiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (ACTION_CALCUlATE.equals(action)) {int first;int second;try {first = Integer.parseInt(intent.getStringExtra("first"));second = Integer.parseInt(intent.getStringExtra("second"));callBack(first, second);} catch (NumberFormatException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}}}};private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {//默认计算1+1 callBack(1, 1);super.handleMessage(msg);}};@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "onBind");return mBinder;}@Overridepublic void onCreate() {Log.d(TAG, "onCreate");// 这里不知道为什么,直接使用callback方法回调showResult// mCallbacks.beginBroadcast()是0,需要用handler延迟1000毫秒// 也许是在activity中binService太耗时的原因?mHandler.sendEmptyMessageDelayed(0, 1000);super.onCreate();IntentFilter filter = new IntentFilter(ACTION_CALCUlATE);registerReceiver(receiver, filter);}@Overridepublic void onDestroy() {mHandler.removeMessages(0);mCallbacks.kill();super.onDestroy();}private void callBack(int first, int second) {int N = mCallbacks.beginBroadcast();try {for (int i = 0; i < N; i++) {mCallbacks.getBroadcastItem(i).showResult(first + second);}} catch (RemoteException e) {Log.e(TAG, "", e);}mCallbacks.finishBroadcast();}}package com.zhang.test;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.widget.Button;import android.widget.CompoundButton;import android.widget.EditText;import android.widget.TextView;import com.zhang.test.service.ICallback;import com.zhang.test.service.IService;import com.zhang.test.service.CalculateService;public class CalculateActivity extends Activity {private static final String TAG = "MainActivity";private IService mService;private EditText first;// 第一个计算数private EditText second;// 第二个计算数private Button calculate;// 计算按钮private TextView result;// 计算结果/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);setUpViews();setUpEvents();Intent i = new Intent(this, CalculateService.class);bindService(i, mConnection, Context.BIND_AUTO_CREATE);}private void setUpViews() {first = (EditText) findViewById(R.id.first);second = (EditText) findViewById(R.id.second);calculate = (Button) findViewById(R.id.calculate);result = (TextView) findViewById(R.id.result);}private void setUpEvents() {calculate.setOnClickListener(new CompoundButton.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(CalculateService.ACTION_CALCUlATE);intent.putExtra("first", first.getText().toString());intent.putExtra("second", second.getText().toString());sendBroadcast(intent);}});}@Overrideprotected void onDestroy() {if (mService != null) {try {mService.unregisterCallback(mCallback);} catch (RemoteException e) {Log.e(TAG, "", e);}}// destroy的时候不要忘记unbindServiceunbindService(mConnection);super.onDestroy();}/** * service的回调方法 */private ICallback.Stub mCallback = new ICallback.Stub() {@Overridepublic void showResult(int result) {Log.d(TAG, "result : " + result);CalculateActivity.this.result.setText(result + "");}};/** * 注册connection */private ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {Log.d(TAG, "onServiceDisconnected");mService = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.d(TAG, "onServiceConnected");mService = IService.Stub.asInterface(service);try {mService.registerCallback(mCallback);} catch (RemoteException e) {Log.e(TAG, "", e);}}};}<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.zhang.test" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CalculateActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity><service android:name=".service.CalculateService" /> </application> <uses-sdk android:minSdkVersion="3" /></manifest>
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="计算:" /> <EditText android:id="@+id/first" android:layout_width="50dip" android:layout_height="wrap_content" android:text="1" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="+" /> <EditText android:id="@+id/second" android:layout_width="50dip" android:layout_height="wrap_content" android:text="1" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="=" /> <TextView android:id="@+id/result" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <Button android:id="@+id/calculate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="go" /></LinearLayout>
