編輯:關於Android編程
什麼是匿名Service?凡是沒有到ServiceManager上注冊的Service,都是匿名Service。
還是拿上一篇的例子來舉例,看代碼:
status_t MediaPlayer::setDataSource(int fd, int64_t offset, int64_t length)
{
status_t err = UNKNOWN_ERROR;
const sp& service(getMediaPlayerService());
if (service != 0) {
sp player(service->create(this, mAudioSessionId));
if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
(NO_ERROR != player->setDataSource(fd, offset, length))) {
player.clear();
}
err = attachNewPlayer(player);
}
return err;
}
在BpMediaPlayerService中,create的實現如下:
virtual sp直接跳到服務端MediaPlayerService,看create的真正實現:create( const sp & client, int audioSessionId) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); data.writeStrongBinder(client->asBinder()); data.writeInt32(audioSessionId); remote()->transact(CREATE, data, &reply); return interface_cast (reply.readStrongBinder()); }
spMediaPlayerService::create(const sp & client, int audioSessionId) { pid_t pid = IPCThreadState::self()->getCallingPid(); int32_t connId = android_atomic_inc(&mNextConnId); sp c = new Client( this, pid, connId, client, audioSessionId, IPCThreadState::self()->getCallingUid()); ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, pid, IPCThreadState::self()->getCallingUid()); /* add by Gary. start {{----------------------------------- */ c->setScreen(mScreen); /* add by Gary. end -----------------------------------}} */ c->setSubGate(mGlobalSubGate); // 2012-03-12, add the global interfaces to control the subtitle gate wp w = c; { Mutex::Autolock lock(mLock); mClients.add(w); } return c; }
從代碼中,我們可以看出,service->create(this, mAudioSessionId)是返回了一個參數為Client類型的BpMediaPlayer對象,其中Client為MediaPlayerService的私有內部類,其聲明為:class Client : publicBnMediaPlayer。這樣,Binder通信的服務端和客戶端就建立起來了。Client端BpMediaPlayer由MediaPlayer使用,Server端BnMediaPlayer由MediaPlayerService使用。
BpMediaPlayer是如何獲得BnMediaPlayer的handle值的呢?答案在MediaPlayerService返回這個binder的引用的時候,binder驅動保存了這個binder實體的各種數據,創建了節點,看下面的代碼:status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp client =
interface_cast(data.readStrongBinder());
int audioSessionId = data.readInt32();
sp player = create(client, audioSessionId);
reply->writeStrongBinder(player->asBinder());
return NO_ERROR;
} break;
……
}
}
答案就在這句話中:reply->writeStrongBinder(player->asBinder());
當這個reply寫到Binder驅動時,驅動會特殊處理這種IBinder類型的數據,為Bbinder建立一個handle。
通信的通路建立後,就可以進行通信了:player->setDataSource(fd, offset, length)
之後的實現,和上一篇講的普通Service就一樣了。
Android SDK三種更新失敗及其解決方法
最近在網上看Moto 360的圖片,真是帥,帥了又帥,比帥更帥。所以想研究下Android wear。更新Android SDK,居然失敗了三次。1.第一次失敗出現Fai
Android Fragment使用之實例演示
Fragment是Android honeycomb 3.0
Android開發學習之路--網絡編程之xml、json
一般網絡數據通過http來get,post,那麼其中的數據不可能雜亂無章,比如我要post一段數據,肯定是要有一定的格式,協議的。常用的就是xml和json了。在此先要搭
Android官方技術文檔翻譯——Eclilpse項目遷移
翻譯工作耗時費神,如果你覺得本文翻譯得還OK,請點擊文末的“頂”;如有錯訛,敬請指正。謝謝。 Eclip