@mSolo
2015-04-10T06:55:54.000000Z
字数 11113
阅读 4056
Android IPC 框架 实战
笔记
https://thenewcircle.com/s/post/1340/Deep_Dive_Into_Binder_Presentation.htm
An IPC/component system for developing object-oriented OS services.
不支持 RPC

public class DownloadClientActivity extends Activity {private static final int CALLBACK_MSG = 0;…@Overridepublic void onClick(View view) {Intent intent = new Intent("com.marakana.android.download.service.SERVICE");ArrayList<Uri> uris = …intent.putExtra("uris", uris);Messenger messenger = new Messenger(new ClientHandler(this));intent.putExtra("callback-messenger", messenger);super.startService(intent);}private static class ClientHandler extends Handler {private final WeakReference<DownloadClientActivity> clientRef;public ClientHandler(DownloadClientActivity client) {this.clientRef = new WeakReference<DownloadClientActivity>(client);}@Overridepublic void handleMessage(Message msg) {Bundle data = msg.getData();DownloadClientActivity client = clientRef.get();if (client != null && msg.what == CALLBACK_MSG && data != null) {Uri completedUri = data.getString("completed-uri");// client now knows that completedUri is done…}}}}public class MessengerDemoService extends IntentService {private static final int CALLBACK_MSG = 0;…@Overrideprotected void onHandleIntent(Intent intent) {ArrayList<Uri> uris = intent.getParcelableArrayListExtra("uris");Messenger messenger = intent.getParcelableExtra("callback-messenger");for (Uri uri : uris) {// download the uri…if (messenger != null) {Message message = Message.obtain();message.what = CALLBACK_MSG;Bundle data = new Bundle(1);data.putParcelable("completed-uri", uri);message.setData(data);try {messenger.send(message);} catch (RemoteException e) {…} finally {message.recycle();}}}}}

Android Interface Definition Language is a Android-specific language for defining Binder-based service interfaces
src/com/example/app/IFooService.aidl
package com.example.app;import com.example.app.Bar;interface IFooService {void save(inout Bar bar);Bar getById(int id);void delete(in Bar bar);List<Bar> getAll();}
命令
$ adb shell service list

// IStockQuoteService.aidlpackage com.stockquote.example;// Declare any non-default types here with import statementsimport com.stockquote.example.StockQuoteRequest;import com.stockquote.example.StockQuoteResponse;interface IStockQuoteService {StockQuoteResponse retrieveStockQuote(in StockQuoteRequest request);}// StockQuoteResponse.aidlpackage com.stockquote.example;ppParcelable StockQuoteResponse;// StockQuoteResponse.javapublic class StockQuoteResponse implements Parcelable {private final StockQuote mResult;public StockQuoteResponse(StockQuote result) {mResult = result;}public StockQuote getResult() {return mResult;}public int describeContents() {return 0;}public void writeToParcel(Parcel parcel, int flags) {parcel.writeSerializable(mResult);}public static final Parcelable.Creator<StockQuoteResponse> CREATOR= new Parcelable.Creator<StockQuoteResponse>() {public StockQuoteResponse createFromParcel(Parcel in) {return new StockQuoteResponse((StockQuote)in.readSerializable());}public StockQuoteResponse[] newArray(int size) {return new StockQuoteResponse[size];}};}

<service android:name="com.stockquote.server.StockQuoteService"><intent-filter><action android:name="com.stockquote.example.IStockQuoteService" /></intent-filter></service>
// StockQuoteServiceImpl.javapublic class StockQuoteServiceImpl extends IStockQuoteService.Stub {private static final String TAG = "StockQuoteServiceImpl";@Overridepublic StockQuoteResponse retrieveStockQuote(StockQuoteRequest request)throws RemoteException {String[] stockIdArray = null;if (request.getType() == StockQuoteRequest.Type.STOCKQUOTE_MULTIPLE) {stockIdArray = request.getStockIdArray();} else {return null;}StockQuote stockQuote = StockNetResourceManager.getInstance().setUpStockQuotes(stockIdArray);return new StockQuoteResponse(stockQuote);}}// StockQuoteServicepublic class StockQuoteService extends Service {private static final String TAG = "StockQuoteService";private StockQuoteServiceImpl mService;@Overridepublic void onCreate() {super.onCreate();mService = new StockQuoteServiceImpl();}@Overridepublic IBinder onBind(Intent intent) {return mService;}@Overridepublic boolean onUnbind(Intent intent) {return super.onUnbind(intent);}@Overridepublic void onDestroy() {mService = null;super.onDestroy();}}// StockNetResourceManager.javapublic class StockNetResourceManager {private static final String URL_STOCK_REC = "http://hq.sinajs.cn/list=";private static final StockNetResourceManager INSTANCE = new StockNetResourceManager();private final OkHttpClient client = new OkHttpClient();private StockNetResourceManager() {}public static StockNetResourceManager getInstance() {return INSTANCE;}public StockQuote setUpStockQuotes(String[] stockIds) {StringBuilder stockRecUrl = new StringBuilder(URL_STOCK_REC);for (String stockId : stockIds) {makeRealStockId(stockId, stockRecUrl);stockRecUrl.append(",");}stockRecUrl.deleteCharAt(stockRecUrl.length() - 1);Request request = new Request.Builder().url(stockRecUrl.toString()).build();try {return cookStockQuote(client.newCall(request).execute().body().string());} catch (IOException e) {e.printStackTrace();}return null;}public StockQuote cookStockQuote(String rawRecs) {// var hq_str_sz002024="苏宁云商,11.26,11.22,11.33,11.45,11.17,11.33,11.34,131241390,1484755809.02,// 153559,11.33,358350,11.32,396400,11.31,654870,11.30,151700,11.29,420400,11.34,315415,11.35,170927,11.36,202600,11.37,111001,11.38,// 2015-03-13,15:05:53,00";// name,open,lastClose,current,highest,lowest,close,**,vol(手),money(元),// after split, the related index will be :String[] stockRecItemArray = rawRecs.split(",");String name = stockRecItemArray[0].split("\"")[1];// hanlde suspend dayif (stockRecItemArray[1].startsWith("0.000")) {return new StockQuote(StockQuote.EVEN_COLOR, name, stockRecItemArray[3],stockRecItemArray[3], stockRecItemArray[3], "+0.00", "+0.00%");}String lastPriceStr = stockRecItemArray[2];String curPriceStr = stockRecItemArray[3];int lastPrice = Integer.parseInt(lastPriceStr.replace(".", ""));int curPrice = Integer.parseInt(curPriceStr.replace(".", ""));int priceColor = StockQuote.EVEN_COLOR;if (curPrice > lastPrice) {priceColor = StockQuote.RISE_COLOR;} else if (curPrice < lastPrice) {priceColor = StockQuote.DOWN_COLOR;}float dividerForGap = 100.00f;float divider = 100.00f;if (name.startsWith("上证指数") || name.startsWith("深证成指")) {dividerForGap = 1000.00f;stockRecItemArray[3] = stockRecItemArray[3].substring(0, stockRecItemArray[3].length() - 1);stockRecItemArray[4] = stockRecItemArray[4].substring(0, stockRecItemArray[4].length() - 1);stockRecItemArray[5] = stockRecItemArray[5].substring(0, stockRecItemArray[5].length() - 1);}String priceGap = String.format("%+.2f", (curPrice - lastPrice)/dividerForGap);String percentage = String.format("%+.2f%%", (curPrice - lastPrice) * divider/lastPrice);return new StockQuote(priceColor, name, stockRecItemArray[3],stockRecItemArray[4], stockRecItemArray[5], priceGap, percentage);}private void makeRealStockId(String stockId, StringBuilder realStockIdBuilder) {if (stockId.startsWith("sh") || stockId.startsWith("sz")) {realStockIdBuilder.append(stockId);return ;}if (stockId.startsWith("600") || stockId.startsWith("601")) {realStockIdBuilder.append("sh").append(stockId);} else {realStockIdBuilder.append("sz").append(stockId);}}}

public class MainActivity extends Activityimplements ServiceConnection {private static final String TAG = "MainActivity";private TextView mNameTv;private TextView mQuoteTv;private IStockQuoteService mService;@Overrideprotected void onCreate(Bundle savedBundle) {super.onCreate(savedBundle);setContentView(R.layout.main);mNameTv = (TextView) findViewById(R.id.name);mQuoteTv = (TextView) findViewById(R.id.quote);}@Overrideprotected void onResume() {super.onResume();if (!super.bindService(new Intent(IStockQuoteService.class.getName()),this, BIND_AUTO_CREATE)) {}}@Overrideprotected void onPause() {super.onPause();super.unbindService(this);}public void onServiceConnected(ComponentName name, IBinder service) {mService = IStockQuoteService.Stub.asInterface(service);setText();}public void onServiceDisconnected(ComponentName name) {mService = null;}private void setText() {final StockQuoteRequest request = new StockQuoteRequest(null,new String[]{"002024"}, StockQuoteRequest.Type.STOCKQUOTE_MULTIPLE);final ProgressDialog dialog = ProgressDialog.show(this, "","正在获取...", true);new AsyncTask<Void, Void, StockQuote>() {@Overrideprotected StockQuote doInBackground(Void... params) {try {StockQuoteResponse response = mService.retrieveStockQuote(request);dialog.dismiss();return response.getResult();} catch (RemoteException e) {Log.wtf(TAG, "Failed to communicate with the service", e);dialog.dismiss();return null;}}@Overrideprotected void onPostExecute(StockQuote result) {dialog.dismiss();if (result == null) {Toast.makeText(MainActivity.this, "获取失败",Toast.LENGTH_LONG).show();} else {mNameTv.setText(result.getStockName());mQuoteTv.setText(result.getStockPrice());}}}.execute();}}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:id="@+id/name"android:gravity="center_horizontal|center_vertical"android:layout_weight="1"android:layout_width="match_parent"android:layout_height="0dp" /><TextViewandroid:id="@+id/quote"android:gravity="center_horizontal|center_vertical"android:layout_weight="1"android:layout_width="match_parent"android:layout_height="0dp" /></LinearLayout>