Android开发进阶之NIO非阻塞包(一)
今天我们继续就AndroidDDMS源码一起分析NIO非阻塞通讯方式,Android123也会给大家分享下手机和PC互通中的一些技术。在NIO中有关SocketChannel和ByteBuffer的使用细节,可以在今天文章中
staticvoidread(SocketChannelchan,byte[]data,intlength,inttimeout)
throwsTimeoutException,IOException{
ByteBufferbuf=ByteBuffer.wrap(data,0,length!=-1?length:data.length);//从字节数组中实例化ByteBuffer
intnumWaits=0;
while(buf.position()!=buf.limit()){//循环接收数据
intcount;
count=chan.read(buf);
if(count<0){
thrownewIOException("EOF");//读到末尾
}elseif(count==0){
if(timeout!=0&&numWaits*WAIT_TIME>timeout){
thrownewTimeoutException();
}
try{
Thread.sleep(WAIT_TIME);
}catch(InterruptedExceptionie){
}
numWaits++;
}else{
numWaits=0;
}
}
}
有关SocketChannel的写操作,就是发送数据代码如下:
staticvoidwrite(SocketChannelchan,byte[]data,intlength,inttimeout)
throwsTimeoutException,IOException{
ByteBufferbuf=ByteBuffer.wrap(data,0,length!=-1?length:data.length);
intnumWaits=0;
while(buf.position()!=buf.limit()){
intcount;
count=chan.write(buf);//发送数据从ByteBuffer中
if(count<0){
thrownewIOException("channelEOF");
}elseif(count==0){
if(timeout!=0&&numWaits*WAIT_TIME>timeout){
thrownewTimeoutException();
}
try{
Thread.sleep(WAIT_TIME);
}catch(InterruptedExceptionie){
}
numWaits++;
}else{
numWaits=0;
}
}
}
有关ADB如何选择一个具体的设备,可以使用setDevice方法,这样当电脑中有模拟器或链接了多个手机,可以通过设备序列号,选择需要通讯的设备。
staticvoidsetDevice(SocketChanneladbChan,IDevicedevice)
throwsTimeoutException,AdbCommandRejectedException,IOException{
//ifthedeviceisnot-1,thenwefirsttelladbwe'relookingtotalk
//toaspecificdevice
if(device!=null){
Stringmsg="host:transport:"+device.getSerialNumber();//最后的获取序列号,android123提示大家在adb命令中是adbget-serialno
byte[]device_query=formAdbRequest(msg);
write(adbChan,device_query);
AdbResponseresp=readAdbResponse(adbChan,false/*readDiagString*/);
if(resp.okay==false){
thrownewAdbCommandRejectedException(resp.message,
true/*errorDuringDeviceSelection*/);
}
}
}
通过PC控制手机重启的代码,当然这里需要Root权限才能执行
publicstaticvoidreboot(Stringinto,InetSocketAddressadbSockAddr,
Devicedevice)throwsTimeoutException,AdbCommandRejectedException,IOException{
byte[]request;
if(into==null){
request=formAdbRequest("reboot:");//$NON-NLS-1$
}else{
request=formAdbRequest("reboot:"+into);//$NON-NLS-1$
}
SocketChanneladbChan=null;
try{
adbChan=SocketChannel.open(adbSockAddr);
adbChan.configureBlocking(false);
//ifthedeviceisnot-1,thenwefirsttelladbwe'relookingtotalk
//toaspecificdevice
setDevice(adbChan,device);
write(adbChan,request);
}finally{
if(adbChan!=null){
adbChan.close();
}
}
}
我们可以看到基本上,每个命令的执行,都是用了单独SocketChannel通过非阻塞方式执行,这样大大加强了并发,所以DDMS可以一边处理Logcat打印,显示堆信息,处理文件管理等等,有关NIO服务器的内容,Android开发网将着重分析MonitorThread.Java这个文件,一起说下NIO的框架。