博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 4.4 WebView实现WebSocket即时通讯
阅读量:7032 次
发布时间:2019-06-28

本文共 11699 字,大约阅读时间需要 38 分钟。

hot3.png

参考博客

 

Android版本要求及H5 api支持情况

在Android版本4.4之前,由于维护和开发Android版本时使用的是AppleWebkit开源内核,虽然也非常不错,但不支持许多html5 api,在Android4.4使用了Chromium才得以发展,

目前支持的html 5如下:

Web Workers 支持 javaScript多线程
WebSocket 支持 javascript套接字,TCP长链接
IDBFactory/indexDB 支持 索引数据库
ApplicationCache 支持 web离线缓存
postMessage/onMessage 支持 收发消息
ondeviceorientation,ondevicemotion,onorientationchange 支持 屏幕旋转,移动
onvolumechange 支持 声音改变
RequestAnimationFrame 支持 页面UI动画更新引擎
LocalStorage/sessionStorage 支持 本地缓存
FileReader 支持 本地文件读取
FormData 支持 模拟表单,表单模型
EventSource 支持 Server-Sent Events(SSE)功能,允许服务端推送数据到客户端。(通常叫数据推送)
CacheStorage 不支持 异步缓存
Promise 不支持 异步范式
Crypto 不支持 javascript加密API
WebAudio 不支持 流媒体播放
WebRTC 不支持 流媒体通讯
WebGL 不支持 Web GL图像框架
GeoLocation 支持 地理定位
Notification 不支持 web通知
Blob 支持 二进制数据对象

 

在这里我们主要了解WebSocket在Android WebView上的支持,这里给出一个基于php WebSocketServer的例子:

【以下例子来自开源中国博客】

体验位置:

请使用你的PC浏览器和你的Android4.4的设备上的浏览器

 

WebSocket Server端实现

php端

master=$this->createSocketServer($address, $port,$maxLink);        $this->sockets=array($this->master);    }         function run()    {        while(true){            $changes=$this->sockets;            $write=NULL;            $except=NULL;                        socket_select($changes,$write,$except,NULL);             /**            *  监听读写操作,socket_select (array &$read, array &$write, array &$except, $tv_sec, $tv_usec = null)            *  $read 注意,这里使用了引用,$read表示要监听读操作的socket,socket_select可以调用多次,之前监听的socket不会被取消(注意,socket连接也是read)            *  $write 注意,这里使用了引用,$read表示要监听写操作的socket,socket_select可以调用多次,之前监听的socket不会被取消            *  $$except 监听异常的socket            *  以上&read,&write,&except是被引用的,也就意味着变量的值可以输入输出,把监听到的socket输出,把想被监听的socket输入            *  最后一个参数是超时时间,默认是0            *              *  该函数会阻塞            */            foreach($changes as $sock){                if($sock==$this->master){                 /**                  * 接受客户端socket                  * @var unknown                  */                    $client=socket_accept($this->master);                    $key=uniqid();                    $this->sockets[]=$client;                    $this->users[$key]=array(                        'socket'=>$client,                        'handshake'=>false                    );                }else{                    $len=0;                    $buffer='';                    do{                        $l=socket_recv($sock,$buf,1000,0);                        $len+=$l;                        $buffer.=$buf;                    }while($l==1000);                    $k=$this->search($sock);                    if($len<7){                        $this->send2($k);                        continue;                    }                    if(!$this->users[$k]['handshake']){                        $this->handshake($k,$buffer);                    }else{                        $buffer = $this->uncode($buffer,$k);                        if($buffer==false){                            continue;                        }                        $this->send($k,$buffer);                    }                }            }                     }             }         function close($k){        socket_close($this->users[$k]['socket']);        unset($this->users[$k]);        $this->sockets=array($this->master);        foreach($this->users as $v){            $this->sockets[]=$v['socket'];        }        $this->e("key:$k close");    }         function search($sock){        foreach ($this->users as $k=>$v){            if($sock==$v['socket'])            return $k;        }        return false;    }         /**     *      * @param string $address 地址     * @param int $port 端口     * @param number $maxLink 最大连接数     */    function createSocketServer($address,$port,$maxLink=16){              $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);        socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);        socket_bind($server, $address, $port);        socket_listen($server,$maxLink);        $this->e('Server Started : '.date('Y-m-d H:i:s'));        $this->e('Listening on   : '.$address.' port '.$port);        return $server;    }          /**      * 握手      * @param string $k 要握手的socket      * @param byte $buffer 缓冲数据      * @return boolean      */    function handshake($k,$buffer){        $buf  = substr($buffer,strpos($buffer,'Sec-WebSocket-Key:')+18);        $key  = trim(substr($buf,0,strpos($buf,"\r\n")));             $new_key = base64_encode(sha1($key."258EAFA5-E914-47DA-95CA-C5AB0DC85B11",true));                 $new_message = "HTTP/1.1 101 Switching Protocols\r\n";        $new_message .= "Upgrade: websocket\r\n";        $new_message .= "Sec-WebSocket-Version: 13\r\n";        $new_message .= "Connection: Upgrade\r\n";        $new_message .= "Sec-WebSocket-Accept: " . $new_key . "\r\n\r\n";                 socket_write($this->users[$k]['socket'],$new_message,strlen($new_message));        $this->users[$k]['handshake']=true;        return true;             }         function uncode($str,$key){        $mask = array();          $data = '';          $msg = unpack('H*',$str);        $head = substr($msg[1],0,2);          if ($head == '81' && !isset($this->sum_length[$key])) {              $len=substr($msg[1],2,2);            $len=hexdec($len);            if(substr($msg[1],2,2)=='fe'){                $len=substr($msg[1],4,4);                $len=hexdec($len);                $msg[1]=substr($msg[1],4);            }else if(substr($msg[1],2,2)=='ff'){                $len=substr($msg[1],4,16);                $len=hexdec($len);                $msg[1]=substr($msg[1],16);            }            $mask[] = hexdec(substr($msg[1],4,2));              $mask[] = hexdec(substr($msg[1],6,2));              $mask[] = hexdec(substr($msg[1],8,2));              $mask[] = hexdec(substr($msg[1],10,2));            $s = 12;            $n=0;        }else if($this->sum_length[$key] > 0){            $len=$this->sum_length[$key];            $mask=$this->salt_key[$key];            $n=$this->per_data_len[$key];            $s = 0;        }                 $e = strlen($msg[1])-2;        for ($i=$s; $i<= $e; $i+= 2) {              $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2)));              $n++;          }          $dlen=strlen($data);                 if($len > 255 && $len > $dlen+intval($this->rec_data_length[$key])){            $this->salt_key[$key]=$mask;            $this->sum_length[$key]=$len;            $this->rec_data_length[$key]=$dlen+intval($this->rec_data_length[$key]);            $this->rec_data_packets[$key]=$this->rec_data_packets[$key].$data;            $this->per_data_len[$key]=$n;            return false;        }else{            unset($this->salt_key[$key],$this->sum_length[$key],$this->rec_data_length[$key],$this->per_data_len[$key]);            $data=$this->rec_data_packets[$key].$data;            unset($this->rec_data_packets[$key]);            return $data;        }             }         function code($msg){        $frame = array();          $frame[0] = '81';          $len = strlen($msg);        if($len < 126){            $frame[1] = $len<16?'0'.dechex($len):dechex($len);        }else if($len < 65025){            $s=dechex($len);            $frame[1]='7e'.str_repeat('0',4-strlen($s)).$s;        }else{            $s=dechex($len);            $frame[1]='7f'.str_repeat('0',16-strlen($s)).$s;        }        $frame[2] = $this->ord_hex($msg);          $data = implode('',$frame);          return pack("H*", $data);      }         function ord_hex($data)  {          $msg = '';          $l = strlen($data);          for ($i= 0; $i<$l; $i++) {              $msg .= dechex(ord($data{$i}));          }          return $msg;      }         //用户加入    function send($k,$msg){        parse_str($msg,$g);        $ar=array();        if($g['type']=='add'){            $this->users[$k]['name']=$g['ming'];            $ar['type']='add';            $ar['name']=$g['ming'];            $key='all';        }else{            $ar['nrong']=$g['nr'];            $key=$g['key'];        }        $this->send1($k,$ar,$key);    }         function getusers(){        $ar=array();        foreach($this->users as $k=>$v){            $ar[]=array('code'=>$k,'name'=>$v['name']);        }        return $ar;    }         /**     * @param string $k 发信息人的code      * @param string $ar 数据     * @param string $key 接受人的 code     */    function send1($k,$ar,$key='all'){        $ar['code1']=$key;        $ar['code']=$k;        $ar['time']=date('m-d H:i:s');        $str = $this->code(json_encode($ar));        if($key=='all'){            $users=$this->users;            if($ar['type']=='add'){                $ar['type']='madd';                $ar['users']=$this->getusers();                $str1 = $this->code(json_encode($ar));                socket_write($users[$k]['socket'],$str1,strlen($str1));                unset($users[$k]);            }            foreach($users as $v){                socket_write($v['socket'],$str,strlen($str));            }        }else{            socket_write($this->users[$k]['socket'],$str,strlen($str));            socket_write($this->users[$key]['socket'],$str,strlen($str));        }    }         //用户退出    function send2($k){        $this->close($k);        $ar['type']='rmove';        $ar['nrong']=$k;        $this->send1(false,$ar,'all');    }         function e($str){        //$path=dirname(__FILE__).'/log.txt';        $str=$str."\n";        //error_log($str,3,$path);        echo iconv('utf-8','gbk//IGNORE',$str);    }}$sk=new Sock('127.0.0.1',8000);$sk->run();?>

WebSocket Client端实现

client端

HTML5 websocket 网页聊天室 javascript php
body,p{margin:0px; padding:0px; font-size:14px; color:#333; font-family:Arial, Helvetica, sans-serif;}#ltian,.rin{width:98%; margin:5px auto;}#ltian{border:1px #ccc solid;overflow-y:auto; overflow-x:hidden; position:relative;}#ct{margin-right:111px; height:100%;overflow-y:auto;overflow-x: hidden;}#us{width:110px; overflow-y:auto; overflow-x:hidden; float:right; border-left:1px #ccc solid; height:100%; background-color:#F1F1F1;}#us p{padding:3px 5px; color:#08C; line-height:20px; height:20px; cursor:pointer; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}#us p:hover,#us p:active,#us p.ck{background-color:#069; color:#FFF;}#us p.my:hover,#us p.my:active,#us p.my{color:#333;background-color:transparent;}button{float:right; width:80px; height:35px; font-size:18px;}input{width:100%; height:30px; padding:2px; line-height:20px; outline:none; border:solid 1px #CCC;}.rin p{margin-right:160px;}.rin span{float:right; padding:6px 5px 0px 5px; position:relative;}.rin span img{margin:0px 3px; cursor:pointer;}.rin span form{position:absolute; width:25px; height:25px; overflow:hidden; opacity:0; top:5px; right:5px;}.rin span input{width:180px; height:25px; margin-left:-160px; cursor:pointer}#ct p{padding:5px; line-height:20px;}#ct a{color:#069; cursor:pointer;}#ct span{color:#999; margin-right:10px;}.c2{color:#999;}.c3{background-color:#DBE9EC; padding:5px;}.qp{position:absolute; font-size:12px; color:#666; top:5px; right:130px; text-decoration:none; color:#069;}#ems{position:absolute; z-index:5; display:none; top:0px; left:0px; max-width:230px; background-color:#F1F1F1; border:solid 1px #CCC; padding:5px;}#ems img{width:44px; height:44px; border:solid 1px #FFF; cursor:pointer;}#ems img:hover,#ems img:active{border-color:#A4B7E3;}#ems a{color:#069; border-radius:2px; display:inline-block; margin:2px 5px; padding:1px 8px; text-decoration:none; background-color:#D5DFFD;}#ems a:hover,#ems a:active,#ems a.ck{color:#FFF; background-color:#069;}.tc{text-align:center; margin-top:5px;}
    
清屏
    
发送    
    

 

 

转载于:https://my.oschina.net/ososchina/blog/644834

你可能感兴趣的文章
在500jsp错误页面获取错误信息
查看>>
iOS-CALayer遮罩效果
查看>>
为什么需要版本管理
查看>>
五、Dart 关键字
查看>>
React Native学习笔记(一)附视频教学
查看>>
记Promise得一些API
查看>>
javascript事件之调整大小(resize)事件
查看>>
20145234黄斐《Java程序设计》第六周学习总结
查看>>
【CLRS】《算法导论》读书笔记(四):栈(Stack)、队列(Queue)和链表(Linked List)...
查看>>
hibernate 和 mybatis区别
查看>>
互联网广告综述之点击率特征工程
查看>>
HDU3421 Max Sum II【序列处理】
查看>>
POJ NOI MATH-7653 地球人口承载力估计
查看>>
iOS UI高级之网络编程(HTTP协议)
查看>>
使用cocoaPods import导入时没有提示的解决办法
查看>>
iOS数据持久化存储之归档NSKeyedArchiver
查看>>
JavaScript面向对象
查看>>
Intellij修改模板代码
查看>>
2.页面布局示例笔记
查看>>
一些老游戏CPU 100%占用的解决方法
查看>>