(一) 概述   

android的binder机制提供一种进程间通信的方法,使一个进程可以以类似远程过程调用的形式调用另一个进程所提供的功能。binder机制在Java环境和C/C++环境都有提供。

android的代码中,与C/C++的binder包括一些类型和接口的定义和实现,相关的代码在下面这几个文件中:

    frameworks\base\include\utils\IInterface.h
    frameworks\base\include\utils\Binder.h
    frameworks\base\include\utils\BpBinder.h
    frameworks\base\include\utils\IBinder
    frameworks\base\include\utils\Parcel.h
    frameworks\base\include\utils\IPCThreadState.h
    frameworks\base\include\utils\ProcessState.h
    frameworks\base\libs\utils\Binder.cpp
    frameworks\base\libs\utils\BpBinder.cpp
    frameworks\base\libs\utils\IInterface.cpp
    frameworks\base\libs\utils\IPCThreadState.cpp
    frameworks\base\libs\utils\Parcel.cpp
    frameworks\base\libs\utils\ProcessState.cpp
    为了了解这些类、接口之间的关系以及binder的实现机制,最好是结合一个例子来进行研究。我选择的例子是android自带的媒体播放器的实现。其媒体播放器的相关代码在下面这些目录中:

frameworks\base\include\media
frameworks\base\media

使用startUML的反向工程功能分析上面这些代码,并进行了一定的整理之后,得到下面这幅类图(点击可查看原尺寸图片)。

android的媒体播放功能分成两部分,一部分是媒体播放应用,一部分是媒体播放服务(MediaServer,在系统启动时由init所启动,具可参考init.rc文件)。这两部分分别跑在不同的进程中。媒体播放应用包括Java程序和部分C++代码,媒体播放服务是C++代码,并且需要调用外部模块opencore来实现真正的媒体播放。媒体播放应用和媒体播放服务之间需要通过binder机制来进行相互调用,这些调用包括:

(1)媒体播放应用向媒体播放服务发控制指令
(2)媒体播放服务向媒体播放应用发事件通知(notify)

媒体播放服务对外提供多个接口,在上面得图中包括其中的2个接口:IMediaService和IMediaPlayer,IMediaplayer用于创建和管理播放实例,而IMediaplayer接口则是播放接口,用于实现指定媒体文件的播放以及播放过程的控制。

上面的图中还有媒体播放应用向媒体播放服务提供的1个接口:IMediaPlayerClient,用于接收notify。

这些接口因为需要跨进程调用,因此需要用到binder机制。每个接口包括两部分实现,一部分是接口功能的真正实现(BnInterface),这部分运行在接口提供进程中;另一部分是接口的proxy(BpInterface),这部分运行在调用接口的进程中。binder的作用就是让这两部分之间建立联系。下图是整个播放器的一个概要说明。

媒体播放器比较复杂一些,总共实现了3个接口,不过要了解binder的机制,只需要研究其中一个接口就足够了。在这里选择IMediaPlayerService接口来看一下。

IMediaPlayerService接口包括六个功能函数:create(url)、create(fd)、decode(url)、decode(fd)、createMediaRecord()、createMetadataRetriever()。在这里不介绍这些函数是做什么的,我们只关注如何通过binder还提供这些函数接口。

(二) 接口定义

(1) 定义接口类

首先定义IMediaPlayerService类,这是一个接口类(C++的术语应该叫纯虚类)。该接口类定义在文件frameworks\base\include\media\IMediaPlayerService.h。代码如下:

class IMediaPlayerService: public IInterface 

public: 
DECLARE_META_INTERFACE(MediaPlayerService); 

virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid) = 0; 
virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0; 
virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) = 0; 
virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0; 
virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; 
virtual sp<IMemory>         decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0; 
}; 
 
    可以看到,在这个接口类中定义了IMediaPlayerService需要提供的6个函数接口,因为是接口类,所以定义为纯虚函数。需要注意这个接口类的名称有严格要求,必须是以大写字母I开始。

重点关注在这些函数前面的一个宏定义: DECLARE_META_INTERFACE(MediaPlayerService)。这个宏定义必须要有,其中封装了实现binder所需要的一些类成员变量和成员函数通过这些成员函数可以为一个binder实现创建proxy。这个宏定义在问价frameworks\base\include\utils\IInterface.h里,在后面还会讲到。这个宏定义的参数必须是接口类的名称去除字母I后剩下的部分。

另外说明一下,可以看到接口类中所定义的函数的返回值都是sp<xxxx>的形式,看起来有点怪异。sp是android中定义的一个模板类,用于实现智能指针功能。sp<IMediaPlayer>就是IMediaPlayer的智能指针,可以简单地把它看成是标准C++中的指针定义即 IMediaPlayer* 即可。

(2) 定义和实现binder类

binder类包括两个,一个是接口实现类,一个接口代理类。接口代理类继承自BpInterface,接口实现类继承自BnInterface。这两个基类都是模板类,封装了binder的进程间通信机制,这样使用者无需关注底层通信实现细节。

对于IMediaPlayerService接口,其binder接口实现类为BnMediaPlayerService,接口代理类为BpMediaPlayerService。需注意这两个类的名称有严格要求,必须以Bn和Bp开头,并且后面的部分必须是前面所定义的接口类的名称去除字母'I’。比如前面所定义的接口类为IMediaPlayerService,去除字母I后是MediaPlayerService,所以两个binder类的名称分别是BnMediaPlayerService和BpMediaPlayerService。为什么有这样的要求?原因就在前面提到的宏定义DECLARE_META_INTERFACE()和另一个宏定义IMPLEMENT_META_INTERFACE()里面。有兴趣的话可以去看一下,这两个宏定义都在文件frameworks\base\include\utils\IInterface.h里。

BpMediaPlayerService是一个最终实现类。定义并且实现在在文件frameworks\base\media\libmidia\IMediaPlayerService.cpp中。在看BpMediaPlayerService的代码之前,先看一下在IMediaPlayerService.cpp文件的开始部分的一个枚举定义:

enum { 
CREATE_URL = IBinder::FIRST_CALL_TRANSACTION, 
CREATE_FD, 
DECODE_URL, 
DECODE_FD, 
CREATE_MEDIA_RECORDER, 
CREATE_METADATA_RETRIEVER, 
}; 

这些6个枚举定义对应于IMediaPlayerService接口所提供的6个功能函数,可以称为这些功能函数的功能代码,用于在进程之间进行RPC是标识需要调用哪个函数。如果不想定义这些枚举值,在后面需要用到这些值的地方直接写上1,2,3,4,5,6也是可以的,不过……一个合适的程序员会这么干吗?

下面看一下BpMediaPlayerService的代码。

(3) BpMediaPlayerService代码分析

class BpMediaPlayerService: public BpInterface<IMediaPlayerService> 

public: 
BpMediaPlayerService(const sp<IBinder>& impl) 
: BpInterface<IMediaPlayerService>(impl) 



virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) 

Parcel data, reply; 
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); 
data.writeInt32(pid); 
remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply); 
return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder()); 


virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) 

Parcel data, reply; 
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); 
data.writeInt32(pid); 
data.writeStrongBinder(client->asBinder()); 
data.writeCString(url); 
remote()->transact(CREATE_URL, data, &reply); 
return interface_cast<IMediaPlayer>(reply.readStrongBinder()); 


virtual sp<IMediaRecorder> createMediaRecorder(pid_t pid) 

Parcel data, reply; 
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); 
data.writeInt32(pid); 
remote()->transact(CREATE_MEDIA_RECORDER, data, &reply); 
return interface_cast<IMediaRecorder>(reply.readStrongBinder()); 


virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) 

Parcel data, reply; 
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); 
data.writeInt32(pid); 
data.writeStrongBinder(client->asBinder()); 
data.writeFileDescriptor(fd); 
data.writeInt64(offset); 
data.writeInt64(length); 
remote()->transact(CREATE_FD, data, &reply); 
return interface_cast<IMediaPlayer>(reply.readStrongBinder()); 


virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 

Parcel data, reply; 
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); 
data.writeCString(url); 
remote()->transact(DECODE_URL, data, &reply); 
*pSampleRate = uint32_t(reply.readInt32()); 
*pNumChannels = reply.readInt32(); 
*pFormat = reply.readInt32(); 
return interface_cast<IMemory>(reply.readStrongBinder()); 


virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) 

Parcel data, reply; 
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); 
data.writeFileDescriptor(fd); 
data.writeInt64(offset); 
data.writeInt64(length); 
remote()->transact(DECODE_FD, data, &reply); 
*pSampleRate = uint32_t(reply.readInt32()); 
*pNumChannels = reply.readInt32(); 
*pFormat = reply.readInt32(); 
return interface_cast<IMemory>(reply.readStrongBinder()); 

}; 

首先可以看到,这个类继承自模板类BpInterface,指定类型为接口类IMediaPlayerService。BpInterface模板类定义在文件IInterface.h。看一下BpInterface的定义就可以发现,BpMediaPlayerService这样定义了以后,事实上间接继承了IMediaPlayerService,从而可以提供IMediaPlayerService接口所定义的接口函数。BpMediaPlayerService需要实现这些接口函数。在一个简单的构造函数之后,就是这些接口函数的实现。可以看到,所有的接口函数的实现方法都是一致的,都是通过binder所提供的机制将参数仍给binder的实现类,并获取返回值。这也就是这个类之所以成为代理类的原因。下面具体看一下一个接口函数。这里选的是函数create(url)。

virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) 

Parcel data, reply; 
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); 
data.writeInt32(pid); 
data.writeStrongBinder(client->asBinder()); 
data.writeCString(url); 
remote()->transact(CREATE_URL, data, &reply); 
return interface_cast<IMediaPlayer>(reply.readStrongBinder()); 

    这个接口函数的参数指定了一个URL,函数将为这个URL创建一个播放器实例用于播放该URL。
    函数首先定义了两个局部变量data和reply,变量的类型都是Parcel。Parcel是一个专为binder通信的数据传送而定义的类,该类提供了对多种类型的数据的封装功能,同时提供多个数据读取和写入函数,用于多种类型的数据的写入和读取,支持的数据类型既包括简单数据类型,也包括对象。这里定义的变量data是用于封装create()函数调用所需要的输入参数,而reply则是用于封装调用的返回数据(包括输出参数的值和函数返回值)。
    函数首先向data中写入各种数据。第一个写入的是接口的一个描述字符串,binder的实现类中会用这个字符串来对接口做验证,防止调用错误。这个字符串也可以不写,如果不写,在binder实现类中相应的也就不要做验证了。跟在描述字符串后面写入的是该接口函数所需要的各种的输入参数。需要说明的是,Pacel提供一种先入先出的数据存储方式,即数据的写入顺序和读取顺序必须严格一致,否则将会出错。
    完成数据写入后,函数调用remote()->transact()用于完成binder通信。transact()函数的第一个参数就是前面提到过的功能代码。transact()的功能是将data中的数据传给binder的实现类,函数调用结束后,reply中将包含返回数据。首先来看看remote()成员函数。前面讲到过BpMediaPlayerService通过继承BpInterface模板类间接继承了IMediaPlayerService接口类,其实BpInterface类是一个有两个父类的多重继承子类,另一个父类是BpRefbase(frameworks\base\include\utils\Binder.h)。remote()就是继承自BpRefBase类的一个成员函数,该函数返回BpRefBase类中定义的一个私有属性mRemote。mRemote是对IBinder接口类的子类BpBinder的一个对象的引用(参考前面的类关系图)。transact()函数在IBinder接口类中定义(frameworks\base\include\utils\Binder.h),并在BpBinder类中实现(frameworks\base\include\utils\BpBinder.h、frameworks\base\libs\utils\BpBinder.cpp)。在transact()函数中将调用IPCThreadState类的transact()函数,并进而通过Lniux内核中的android共享内存驱动来实现进程间通信。不过这些细节这里就不多说了。在这里BpBinder类对象是一个关键,是实现Binder代理的核心之一。BpBinder类可以看成是一个通信handle(类似于网络编程中的socket),用于实现进程间通信。接下来需要研究的是这个BpBinder类对象(即mRemote成员变量的值)是从哪里来的。
    回过头来BpMediaPlayerService的构造函数(看前面的代码)。该构造函数的参数是一个IBinder对象的引用。mRemote的值就是在这里传进来的这个对象。那么这个对象又是怎么来的呢?要搞清楚这一点就需要找到创建BpMediaPlayerService类的实例的代码,这个代码就就跟在该类的定义代码的下面。继续看IMediaPlayerService.cpp文件,在BpMediaPlayerService类定义的后面,是下面这样一行代码:

IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.hardware.IMediaPlayerService"); 

    这行代码调用了一个宏定义IMPLEMENT_META_INTERFACE()。这个宏定义与前面提到过的DECLARE_META_INTERFACE()相呼应。看名字就知道,IMPLEMENT_META_INTERFACE()宏是对DECLARE_META_INTERFACE()所定义的成员函数的具体实现。这个宏的第一个参数与DECLARE_META_INTERFACE()的参数需完全一样,第二参数是接口的描述字符串(这个字符串前面也已经讲到过了)。描述字符串不重要,重要的是宏里面定义的一个静态成员函数asInterface()。BpMediaPlayerService的类实例是在IMediaPlayerService的静态成员函数asInterface()中创建的,在IInterface.h中定义了一个内联函数interface_cast(),对这个成员函数进行了封装。通过看代码容易知道,BpMediaPlayerService的构造函数的参数是通过interface_cast()的参数传进来的。
    好,下面就该看看这个interface_cast()是在哪里调用的,它的参数到底是什么。找到frameworks\base\media\libmedia\mediaplayer.cpp文件,其中的MediaPlayer::getMediaPlayerService()的实现代码:
const sp<IMediaPlayerService>& MediaPlayer::getMediaPlayerService() 

Mutex::Autolock _l(sServiceLock); 
if (sMediaPlayerService.get() == 0) { 
sp<IServiceManager> sm = defaultServiceManager(); 
sp<IBinder> binder; 
do { 
binder = sm->getService(String16("media.player")); 
if (binder != 0) 
break; 
LOGW("MediaPlayerService not published, waiting..."); 
usleep(500000); // 0.5 s 
} while(true); 
if (sDeathNotifier == NULL) { 
sDeathNotifier = new DeathNotifier(); 

binder->linkToDeath(sDeathNotifier); 
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder); 

LOGE_IF(sMediaPlayerService==0, "no MediaPlayerService!?"); 
return sMediaPlayerService; 

    看一下上面这段代码中的红色字体部分。结合前面的分析,可知BpBinder类的对象实例是从android的服务管理器的getService()函数中获取,进一步追进去,会发现下面这样一段代码:


Parcel data, reply; 
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); 
data.writeString16(name); 
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); 
return reply.readStrongBinder(); 

    Android的服务管理器是一个单独的进程,也向外提供接口。这段代码的含义,是通过Android的服务管理器的接口代理,请求调用服务管理器的checkService()接口函数,查找指定的服务(上面就是查找media.player服务),查找成功后返回一个BpBinder类的对象实例,用于供IMediaPlayerService代理使用。这个对象BpBinder是在Parcel::readStrongBinder()函数里面创建的。那么到底是怎么创建出来的呢?在这里没有必要追到ServiceManager的实现代码里去,毕竟我们只是想知道BpBinder的对象是如何创建的,我们可以换一个例子来看。回到前面的BpMediaPlayerService::create()函数的实现,是不是很眼熟。没错,在那个函数里也创建了一个BpBinder类对象,那个对象是是给IMediaPlayer接口代理使用的。虽然接口不同,但是创建原理是一样的。我们继续,下面该到binder的另一个类——实现类的代码了。

(3) BnMediaPlayerService代码分析
    BnMediaPlayerService类的定义在文件frameworks\base\include\media\IMediaPlayService.h,实现则与BpMediaPlayerService一样是在文件frameworks\base\media\libmidia\IMediaPlayerService.cpp中。类定义的代码如下:
class BnMediaPlayerService: public BnInterface<IMediaPlayerService> 

public: 
virtual status_t    onTransact( uint32_t code, 
const Parcel& data, 
Parcel* reply, 
uint32_t flags = 0); 
}; 

    这个类继承自BnInterface模板类,约束类型为IMediaPlayerService。看一下BnInterface模板类的定义(IInterface.h)就可以知道,BnMediaPlayerService间接继承了IMediaPlayerService接口类。不过BnInterface类并没有实现IMediaPlayerService所定义的6个接口函数,因此BnInterface还是一个纯虚类。这些接口需要在BnMediaPlayerService的子类中真正实现,这个子类就是MediaPlayerService(frameworks\base\media\libmidiaservice\MediaPlayerService.h,frameworks\base\media\libmidiaservice\MediaPlayerService.cpp)。在BnMediaPlayerService的成员函数onTransact()中,需要调用这6个接口函数。BnMediaPlayerService中主要就是定义并实现了onTransact()函数。当在代理那边调用了transact()函数后,这边的onTransact()函数就会被调用。BnMediaPlayerService的实现代码如下:
#define CHECK_INTERFACE(interface, data, reply) \ 
do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \ 
LOGW("Call incorrectly routed to " #interface); \ 
return PERMISSION_DENIED; \ 
} } while (0) 

status_t BnMediaPlayerService::onTransact( 
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 

switch(code) { 
case CREATE_URL: { 
CHECK_INTERFACE(IMediaPlayerService, data, reply); 
pid_t pid = data.readInt32(); 
sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder()); 
const char* url = data.readCString(); 
sp<IMediaPlayer> player = create(pid, client, url); 
reply->writeStrongBinder(player->asBinder()); 
return NO_ERROR; 
} break; 
case CREATE_FD: { 
CHECK_INTERFACE(IMediaPlayerService, data, reply); 
pid_t pid = data.readInt32(); 
sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder()); 
int fd = dup(data.readFileDescriptor()); 
int64_t offset = data.readInt64(); 
int64_t length = data.readInt64(); 
sp<IMediaPlayer> player = create(pid, client, fd, offset, length); 
reply->writeStrongBinder(player->asBinder()); 
return NO_ERROR; 
} break; 
case DECODE_URL: { 
CHECK_INTERFACE(IMediaPlayerService, data, reply); 
const char* url = data.readCString(); 
uint32_t sampleRate; 
int numChannels; 
int format; 
sp<IMemory> player = decode(url, &sampleRate, &numChannels, &format); 
reply->writeInt32(sampleRate); 
reply->writeInt32(numChannels); 
reply->writeInt32(format); 
reply->writeStrongBinder(player->asBinder()); 
return NO_ERROR; 
} break; 
case DECODE_FD: { 
CHECK_INTERFACE(IMediaPlayerService, data, reply); 
int fd = dup(data.readFileDescriptor()); 
int64_t offset = data.readInt64(); 
int64_t length = data.readInt64(); 
uint32_t sampleRate; 
int numChannels; 
int format; 
sp<IMemory> player = decode(fd, offset, length, &sampleRate, &numChannels, &format); 
reply->writeInt32(sampleRate); 
reply->writeInt32(numChannels); 
reply->writeInt32(format); 
reply->writeStrongBinder(player->asBinder()); 
return NO_ERROR; 
} break; 
case CREATE_MEDIA_RECORDER: { 
CHECK_INTERFACE(IMediaPlayerService, data, reply); 
pid_t pid = data.readInt32(); 
sp<IMediaRecorder> recorder = createMediaRecorder(pid); 
reply->writeStrongBinder(recorder->asBinder()); 
return NO_ERROR; 
} break; 
case CREATE_METADATA_RETRIEVER: { 
CHECK_INTERFACE(IMediaPlayerService, data, reply); 
pid_t pid = data.readInt32(); 
sp<IMediaMetadataRetriever> retriever = createMetadataRetriever(pid); 
reply->writeStrongBinder(retriever->asBinder()); 
return NO_ERROR; 
} break; 
default: 
return BBinder::onTransact(code, data, reply, flags); 


    首先是一个宏定义CHECK_INTERFACE(),这个宏定义的作用是检查接口的描述字符串,这个前面也提到过,不需细说。然后就是onTrasact()函数的实现。这个函数的结构也很简单,就是根据参数code的值分别执行不同的功能调用。code的取值就是前面提到过的接口功能代码。函数的参数除了code,还包括Parcel类的两个对象data和reply,分别用于传送输入参数和返回数据,与transact()函数的参数相对应。还有一个参数flag在这里用不上,不讨论。对应我们前面所选择的接口函数的例子create(url),看看这边对应的实现:
case CREATE_URL: { 
CHECK_INTERFACE(IMediaPlayerService, data, reply); 
pid_t pid = data.readInt32(); 
sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder()); 
const char* url = data.readCString(); 
sp<IMediaPlayer> player = create(pid, client, url); 
reply->writeStrongBinder(player->asBinder()); 
return NO_ERROR; 

    首先是从data对象中依次取出各项输入参数,然后调用接口函数create()(将在子类MediaPlayerService中实现),最后向reply中写入返回数据。这个函数返回后,代理那边的transact()也会跟着返回。
    那么onTransact()函数是怎么被调用的呢?通过查看BnInterface模板类的定义可以看到,这个类也是一个多重继承类,另一个父类是BBinder(frameworks\base\include\utils\Binder.h,frameworks\base\libs\utils\Binder.cpp)。BBinder类继承自IBinder,也实现了transact()函数,在这个函数中调用onTransact()函数。而BBinder对象的transact()函数则是在IPCThreadState类的executeCommand()成员函数中调用的。这已经涉及到较底层的实现,在这里不再多说。
    上面这部分代码还与前面提到过的BpBinder对象的创建有关系。看其中的红色字体部分,通过create()函数调用会创建一个IMediaPlayer接口类的子类的对象,这个对象其实是MediaPlayerService::Client类(可以看一下MediaPlayerService的定义)的对象实例,而MediaPlayerService::Client类是继承自BnMediaPlayer类的,与BnMediaPlayerService类类似,BnMediaPlayer其实也是一个binder实现类(是BBinder的子类,进而也是IBinder的子类)。在上述代码中,通过Parcel的writeStrongBinder()函数将这个对象写入reply,而在代理侧,通过Parcel的readStrongBinder()函数读取则可以得到一个BpBinder的对象。至于类的具体创建过程已经封装在Parcel类的定义中,这里就不再多说了。

(4) 接口功能的真正实现
    到这里两个binder类就已经定义完了,下面就是IMediaPlayerService接口函数的真正实现。前面已经说过这些函数在类MediaPlayerService中实现。这个类继承自BnMediaPlayerService,也间接地继承了IMediaPlayerService接口类定义的6个功能函数,只需要按照正常方式实现这6个功能函数即可,当然为了实现这6个函数就需要其它一大堆的东西,不过这些具体的实现方法已经与binder机制无关,不再多说。
   在MediaPlayerService类中定义了一个静态函数instantiate(),在这个函数中创建MediaPlayerService的对象实例,并将这个对象注册到服务管理器中。这样需要使用的时候就可以从服务管理器获取IMediaPlayerService的代理对象。这个instantiate()是在MediaServer程序的main()函数中调用的。
void MediaPlayerService::instantiate() { 
defaultServiceManager()->addService( 
String16("media.player"), new MediaPlayerService()); 


(三) 总结一下
    说了这么多,总结一下。下图是binder机制的层次模型。

    如果一个服务需要通过binder机制对外提供跨进程的接口,需要做下面这些事情。
    (1) 第一步,需要为这个接口定义一个继承自IInterface的接口类,假设叫做IMyService。
    (2) 第二步,需要定义两个binder类,其中一个是代理类BpMyService,需继承自BpInterface;另一个是实现类BnMyService,需继承自BnInterface。
    (3) 第三步,定义BnMyService的子类,这个子类可以是任何名字,比如就叫MyService,在其中真正实现接口所提供的各个函数。
    (4) 第四步,创建MyService的实例,注册到服务管理器(如IMediaPlayerService),也可以在其它接口的函数中创建(如上面的IMediaPlayer)。
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 七、CrawlSpider实现微信小程序社区爬虫--scrapy爬虫初学者学习过程-----精通Python爬虫框架scrapy

    七、CrawlSpider实现微信小程序社区爬虫作者:Irain QQ:2573396010 微信:18802080892 视频资源链接:https://www.bilibili.com/video/BV1P4411f7rP?p=83.1 创建项目和CrawlSpider爬虫 1.1 在DOC窗口创建项目和CrawlSpider爬虫 scrapy startproject wxapp # 创建项目 cd wx…...

    2024/4/17 4:08:37
  2. phython 网络爬虫意思

    Python爬虫,从网站某一个页面(通常是首页)开始,读取网页的内容,找到在网页中的其它链接地址,然后通过这些链接地址寻找下一个网页,这样一直循环下去,直到把这个网站所有的网页都抓取完为止。如果把整个互联网当成一个网站,那么网络蜘蛛就可以用这个原理把互联网上所有的…...

    2024/3/31 21:05:20
  3. Android 音视频学习:MediaCodec录制MP4文件

    概述 这片博客的目标完成音频的硬编码和硬解码 完成视频的硬编码和硬解码 完成音视频的录制MP4此篇博客仅作为笔记使用,以防以后忘记 MediaCodec介绍 在Android 4.1版本提供了MediaCodec来访问设备的编解码器,它采用的是硬件编解码,所以在速度上比软解码更有优势 MediaCodec…...

    2024/4/17 4:08:49
  4. 从源码解析-Android中进程间通信Binder机制之Service Manager 启动【三】

    源码路径如下:framework/native/cmds/servicemanager/service_manager.c binder.c具体功能如下: SM本身也是一个Server,是Binder IPC通信过程中的守护进程,负责所有Server进程的注册,并处理Client进程的查询 Service Manager 启动 前面说过,如果网络要能够使用,那DNS就必…...

    2024/4/18 17:03:00
  5. 微信小程序和公众号开发流程

    最近在公司参与微信小程序的开发,小程序近几年非常火,通过最近的学习分享一下开发微信小程序的流程1、了解一下微信官方开发公众号文档微信官方文档-公众号对文档介绍有一个大致的印象,然后开始动手配置2、申请微信号,官方提供的测试号平台微信平台-测试号管理申请测试号以…...

    2024/4/17 4:08:37
  6. 《高效能人士的七个习惯》精简总结

    ——陈 习惯一 积极主动 自我意识、想象力、良知、独立意志是人类的四大天赋(主导一切VS被动适应)。 习惯二 以终为始 对方向和目的清晰的构思(即愿景),使命,梦想,宣言。see-do-get 习惯三 要事第一 有无数的事要做,有无数的知识要学习,有无数种乐趣去体验。紧急重…...

    2024/4/18 16:18:48
  7. Fragment应用实战告别ActivityGroup

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/13171191现在Fragment的应用真的是越来越广泛了,之前Android在3.0版本加入Fragment的时候,主要是为了解决Android Pad屏幕比较大,空间不能充分利用的问题,但现在即使只是在手机上,也有很多的场景可以运…...

    2024/4/18 0:18:57
  8. 爬虫常见面试

    一.项目问题: 1.你写爬虫的时候都遇到过什么反爬虫措施,你最终是怎样解决的通过headers反爬虫:解决策略,伪造headers 基于用户行为反爬虫:动态变化去爬取数据,模拟普通用户的行为, 使用IP代理池爬取或者降低抓取频率,或 通过动态更改代理ip来反爬虫 基于动态页面的反爬…...

    2024/4/17 4:08:37
  9. 笔记:《高效能人士的七个习惯》第四章 习惯二 以终为始——自我领导的原则

    1、太多人成功后,反而感到空虚;得到名利之后,却发现牺牲了更可贵的东西。因此,我们务必盯紧真正重要的愿景,然后勇往直前坚持到底,使生活充满意义。 2、和内在力量相比,身外之物显得微不足道。——奥利弗.温德尔.霍姆斯(Oliver Wendell Holmes)美国最高法院前大法官 一…...

    2024/4/25 20:45:55
  10. Android Binder机制介绍

    转载于:http://www.cnblogs.com/zc9527/p/5638688.html备注:该博客简单介绍类型的做过Android开发的同学可能有些体会,入门初期,工作内容主要是实现各式各样的UI界面,以及实现应用的业务逻辑。在这个阶段,我们会逐渐熟悉View系统,逐渐学会实现各种各样的界面以及动画效果…...

    2024/4/17 4:09:49
  11. Tablayout+viewPager+懒加载快速实现一个导航模型

    商城项目中使用最多的就是这个套路 - 各种订单列表,各种商品展示。每次布局的时候就想VC过来。所以就要频繁的去查找之前的写的代码,中间各种剔除逻辑。烦不胜烦。所以就 记录下大概模型。下次直接从博客拷贝。Actvity类中的 xml<?xml version="1.0" encoding=…...

    2024/4/17 4:08:55
  12. JAVA微信公众号开发

    微信公众号开发文档:https://mp.weixin.qq.com/wiki微信公众平台接口调试工具:https://mp.weixin.qq.com/debug/cgi-bin/apiinfoJAVA微信公众号开发框架:Wechat4jWechat4j帮助文档:http://www.chengn.com/wechat4j/wiki/jieruzhinan.html*********************************…...

    2024/4/17 4:10:01
  13. 7.matlab中使用@ + “函数名”

    总是会面临,根据选择的不同的值,获得不同 函数。就类似于switch 中的问题switch Fcase F1fobj = @F1;lb=-100;ub=100;dim=30;case F2fobj = @F2lb=-10;ub=10;dim=30;end function o = F1(x) % o = sum(x.^2); This is the advantage of matrix o=sum((x).^2); en…...

    2024/4/17 4:10:12
  14. ActivityGroup中的子Activity创建Dialog:android.view.WindowManager$BadTokenException: U

    我们在ActivityGroup或者TabActivity中的子Activity创建Dialog若使用以下的代码progressDialog = new ProgressDialog(XXX.this)创建就会出现如下Exception:05-24 12:34:42.236: ERROR/AndroidRuntime(6362): android.view.WindowManager$BadTokenException: Unable to add win…...

    2024/3/31 18:08:05
  15. 爬虫的基本原理介绍

    爬虫的基本原理介绍一、什么是爬虫爬虫:请求网站并提取数据的自动化程序百科:网络爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、…...

    2024/4/20 11:12:24
  16. MATLAB安装问题解决方案大集锦

    我的安装后的两个问题 第一个:“Microsoft Visual C++ Runtime LibraryRuntime Error!Program:C:\Matlab7\Rin\Win32\Matlab.exeThis application has requested the runtime to terminate it in an unusual way.Please contact the applications support team for more infor…...

    2024/4/17 4:09:37
  17. 仿写系统AIDL框架 学习Binder机制

    仿写系统AIDL框架 学习Binder机制 目的:通过仿写AIDL加深对Android应用层和Framework层中应用的Binder机制的理解。 AIDL(Android接口定义语言)是一种框架,对Binder的封装。帮助我们方便的去使用Binder。如果直接用Binder需要写很多代码,采用AIDL可能只需要几行。就能完成…...

    2024/4/17 4:09:55
  18. 搭建zookeeper服务器

    简介ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错…...

    2024/4/4 22:22:48
  19. vue 微信公众号开发

    vue 微信公众号开发开题上个月初入职了一家新公司。来了新公司很忙。本来计划是在上个月底写一篇博客的,写一下关于新公司的事情。 几度思考之后还是没写。也许做程序员接手别人的项目,都会说别人的项目多么的坑吧。但是我接手的这个两个 不是我一个人说坑。各种非人道的东…...

    2024/4/18 6:49:01
  20. 使用ActivityGroup 时子选项卡activity里的EditText只能输入无法删除问题

    在Fragment 和FragmentManager 没出来之前,使用activitygroup 控制多个activity 时,在activity里的 edittext 老是不能删除文字,试着把edittext 放在fragment里面,结果还是一样不能删除! 在网上看到了篇文章,说是子选项卡里面的回退删除选项,有一部分是activitygroup …...

    2024/4/29 1:46:39

最新文章

  1. face_recognition+python-opencv实现摄像头实时人脸识别

    参考&#xff1a; https://www.jianshu.com/p/9d5f0020acd5 完整代码 # -*- coding: utf-8 -*-import face_recognitionimport cv2import oscamera cv2.VideoCapture(0)font cv2.FONT_HERSHEY_DUPLEXface_names []face_codings []person_list os.listdir("faces/&quo…...

    2024/5/3 23:30:24
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. C# Solidworks二次开发:六种配合方式以及注意事项API详解

    今天要写的文章是关于配合的一些API介绍。 如果大家还不知道创建配合的API用的是哪个&#xff0c;可以看一下我之前写的文章&#xff1a;C# Solidworks二次开发&#xff1a;创建距离配合以及移动组件API详解_solidworks transform2-CSDN博客 &#xff08;1&#xff09;今天要…...

    2024/5/3 11:49:19
  4. 基于AI智能识别技术的智慧展览馆视频监管方案设计

    一、建设背景 随着科技的不断进步和社会安全需求的日益增长&#xff0c;展览馆作为展示文化、艺术和科技成果的重要场所&#xff0c;其安全监控系统的智能化升级已成为当务之急。为此&#xff0c;旭帆科技&#xff08;TSINGSEE青犀&#xff09;基于视频智能分析技术推出了展览…...

    2024/4/30 17:11:11
  5. vscode安装通义灵码

    作为vscode的插件&#xff0c;直接使用 通义灵码-灵动指间&#xff0c;快码加编&#xff0c;你的智能编码助手 通义灵码&#xff0c;是一款基于通义大模型的智能编码辅助工具&#xff0c;提供行级/函数级实时续写、自然语言生成代码、单元测试生成、代码注释生成、代码解释、研…...

    2024/5/3 8:55:29
  6. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/5/1 17:30:59
  7. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/5/2 16:16:39
  8. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  9. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/5/3 23:10:03
  10. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  11. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  12. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  13. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  14. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  15. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/5/2 15:04:34
  16. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  17. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  18. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  19. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  20. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  21. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  22. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  23. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  24. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/5/2 9:07:46
  25. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  26. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  27. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  28. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  29. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  30. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  31. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  32. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  33. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  34. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  35. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  36. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  37. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  38. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  39. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  40. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  41. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  42. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  43. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  44. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  45. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57