@mSolo
2015-04-10T14:55:54.000000Z
字数 11113
阅读 3929
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;
…
@Override
public 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);
}
@Override
public 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;
…
@Override
protected 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.aidl
package com.stockquote.example;
// Declare any non-default types here with import statements
import com.stockquote.example.StockQuoteRequest;
import com.stockquote.example.StockQuoteResponse;
interface IStockQuoteService {
StockQuoteResponse retrieveStockQuote(in StockQuoteRequest request);
}
// StockQuoteResponse.aidl
package com.stockquote.example;pp
Parcelable StockQuoteResponse;
// StockQuoteResponse.java
public 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.java
public class StockQuoteServiceImpl extends IStockQuoteService.Stub {
private static final String TAG = "StockQuoteServiceImpl";
@Override
public 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);
}
}
// StockQuoteService
public class StockQuoteService extends Service {
private static final String TAG = "StockQuoteService";
private StockQuoteServiceImpl mService;
@Override
public void onCreate() {
super.onCreate();
mService = new StockQuoteServiceImpl();
}
@Override
public IBinder onBind(Intent intent) {
return mService;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
mService = null;
super.onDestroy();
}
}
// StockNetResourceManager.java
public 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 day
if (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 Activity
implements ServiceConnection {
private static final String TAG = "MainActivity";
private TextView mNameTv;
private TextView mQuoteTv;
private IStockQuoteService mService;
@Override
protected void onCreate(Bundle savedBundle) {
super.onCreate(savedBundle);
setContentView(R.layout.main);
mNameTv = (TextView) findViewById(R.id.name);
mQuoteTv = (TextView) findViewById(R.id.quote);
}
@Override
protected void onResume() {
super.onResume();
if (!super.bindService(new Intent(IStockQuoteService.class.getName()),
this, BIND_AUTO_CREATE)) {
}
}
@Override
protected 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>() {
@Override
protected 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;
}
}
@Override
protected 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">
<TextView
android:id="@+id/name"
android:gravity="center_horizontal|center_vertical"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
<TextView
android:id="@+id/quote"
android:gravity="center_horizontal|center_vertical"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
</LinearLayout>