安卓编程实现wifi聊天,视频和音频通话

安卓编程实现wifi聊天,视频和音频通话

安卓编程实现wifi聊天,传文件,视频和音频通话
在移动开发的过程中,即时通讯是许多app必须要用到的功能,许多app都没有自主开发自己的聊天系统,反而引用了第三方的即时通讯sdk,贵还不说,有时候想自己增加功能也是麻烦,本文通过安卓编程为例,使用wifi作为服务器,实现了安卓即时通讯和视频音频的通话功能。

安卓开启热点服务
安卓系统自带的热点服务,本次编程将热点开启作为局域网的聊天服务器,一台手机作为主服务器搭建聊天服务。
热点创建服务代码如下
public void createServer(){

try {


// System.out.println(“本机ip:”+getLocalIpAddress());
ServerSocket ss = new ServerSocket(30000);
while (true) {

        String localip= getHostIP();
        System.out.println("本机ip:"+localip);

        Socket s = ss.accept(); 
        System.out.println("已连接ip:"+s.getInetAddress().toString());
        vibrators();


// showNot(“已连接ip:”+s.getInetAddress().toString());
simpleNotice(“已连接ip:”+s.getInetAddress().toString());
socketList.add(s);
new Thread(new ServerThead(s,handler)).start();

        Intent intent = new Intent();
        intent.setAction("www.ailiaw.com.mywifi");//设置意图
        intent.putExtra("action", "newmsg");//设置所需发送的消息标签以及内容


// BroadCastActivity.this.sendBroadcast(intent);
SimpleServer.this.sendOrderedBroadcast(intent,null);//有序广播
}
} catch (IOException e) {
e.printStackTrace();
}
}

客户端也是由安卓手机来接受的,使用普通的Socket连接即可
public void createConnection() {
try {
socket = new Socket(ip, port);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if (socket != null) {
try {
socket.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if (socket != null) {
try {
socket.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
} finally {
}
}

Socket客户端发送文本消息方法
public void sendMessage(String sendMessage) {
try {
out = new DataOutputStream(socket.getOutputStream());
if (sendMessage.equals(“Windows”)) {
out.writeByte(0x1);
out.flush();
return;
}
if (sendMessage.equals(“Unix”)) {
out.writeByte(0x2);
out.flush();
return;
}
if (sendMessage.equals(“Linux”)) {
out.writeByte(0x3);
out.flush();
} else {
out.writeUTF(sendMessage);
out.flush();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if (out != null) {
try {
out.close();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
}

视频聊天原理:安卓编程获取SurfaceView的视频流转成图片流发送,另一端则接收实时展示图片,形成了动画视频
//获取摄像头流并开启线程通过socket发送
private void initCamera() {
if (!isPreview) {

    if (null == camera) {
        // 打开前置摄像头
        int cameraCount = 0;
        @SuppressWarnings("unused")
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras(); // get cameras number
        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                //代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
                try {
                    camera = Camera.open(camIdx);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }
    }
    //前置摄像头为空则切换后摄像头
    if (null == camera) {
        // 打开前后置摄像头
        int cameraCount = 0;
        @SuppressWarnings("unused")
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        cameraCount = Camera.getNumberOfCameras(); // get cameras number
        for (int camIdx = 0; camIdx < cameraCount; camIdx++) {
            Camera.getCameraInfo(camIdx, cameraInfo); // get camerainfo
            if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                //代表摄像头的方位,目前有定义值两个分别为CAMERA_FACING_FRONT前置和CAMERA_FACING_BACK后置
                try {
                    camera = Camera.open(camIdx);
                } catch (RuntimeException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }
    }


// camera = Camera.open();
ClientThread.size = camera.getParameters().getPreviewSize();
}
if (camera != null && !isPreview) {
try {
camera.setPreviewDisplay(sfh); // 通过SurfaceView显示取景画面
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(screenWidth, screenHeight / 4 * 3);
/* 每秒从摄像头捕获5帧画面, */
parameters.setPreviewFrameRate(5);
parameters.setPictureFormat(ImageFormat.NV21); // 设置图片格式
parameters.setPictureSize(screenWidth, screenHeight / 4 * 3); // 设置照片的大小
camera.setDisplayOrientation(90);
camera.setPreviewCallback(new PreviewCallback() {

                @Override
                public void onPreviewFrame(byte[] data, Camera c) {
                    // TODO Auto-generated method stub
                    Size size = camera.getParameters().getPreviewSize();
                    try {
                        //调用image.compressToJpeg()将YUV格式图像数据data转为jpg格式
                        YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width, size.height, null);
                        if (image != null) {
                            Message msg = clientThread.revHandler.obtainMessage();
                            msg.what = 0x111;
                            msg.obj = image;
                            clientThread.revHandler.sendMessage(msg);

                            /*outstream = new ByteArrayOutputStream();
                            image.compressToJpeg(new Rect(0, 0, size.width, size.height), 80, outstream);
                            outstream.flush();
                            new Thread(clientThread).start();*/
                        }
                    } catch (Exception ex) {
                        Log.e("Sys", "Error:" + ex.getMessage());
                    }
                }

            });
            camera.startPreview();                                   // 开始预览
            camera.autoFocus(null);                                  // 自动对焦
        } catch (Exception e) {
            e.printStackTrace();
        }
        isPreview = true;
    }
}


//接收视频流转为图片展示
byte [] buffer = new byte[1024];
int len = 0;

try {
    ss = new ServerSocket(40000);
} catch (IOException e2) {
    // TODO Auto-generated catch block
    e2.printStackTrace();
    return;
}

InputStream ins = null;
while(true){

    try {
        s = ss.accept();
        Log.e("strat","ljq");
        ins = s.getInputStream();

        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        while( (len=ins.read(buffer)) != -1){
            outStream.write(buffer, 0, len);
        }
        ins.close();
        byte data[] = outStream.toByteArray();
        bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

        Message msg =handler.obtainMessage();
        msg.what = COMPLETED;
        msg.obj = bitmap;
        handler.sendMessage(msg);

        outStream.flush();
        outStream.close();
        if(!s.isClosed()){
            s.close();
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return;
    }
    //Bitmap bitmap = BitmapFactory.decodeStream(ins);

}


安卓语音聊天则是通过AudioRecord获取音频流,通过Socket发送,另一端则接收音频流,再通过AudioTrack实时播放出来
.//采集声音并发送
class RecordPlayThread extends Thread{
@SuppressLint(“WrongConstant”)
public void run(){
try{

//byte 文件来存储声音
byte[] buffer = new byte[recBufSize];

//开始采集声音
audioRecord.startRecording();

//播放声音
// audioTrack.play();

        int frame_size = 320;//g726_32 : 4:1的压缩比

        short [] encodeData = new short[frame_size/2];

        while(isRecording){



           /* int bufferReadResult  = audioRecord.read(encodeData, 0, 160);


// calc1(encodeData,0,160);
test_Noise(encodeData,160);

            int wirteNum = audioTrack.write(encodeData, 0, bufferReadResult);*/

            //从MIC存储到缓存区
           int bufferReadResult = audioRecord.read(buffer,0, recBufSize);
            byte[] tmpBuf = new byte[bufferReadResult];





            System.arraycopy(buffer, 0, tmpBuf, 0, bufferReadResult);

            Message msg = clientThread.revHandler.obtainMessage();
            msg.what = 0x111;
            msg.obj = tmpBuf;
            clientThread.revHandler.sendMessage(msg);

            //播放缓存区的数据


// audioTrack.write(tmpBuf, 0, tmpBuf.length);

        }

1
// audioTrack.stop();
// audioRecord.stop();
audioRecord.stop();
audioRecord.release();
audioRecord = null;
// audioTrack.stop();
// audioTrack.release();
// audioTrack = null;
}catch(Throwable t){
Toast.makeText(RecordActivity.this, t.getMessage(),1000);
}
}
};

}

//接收音频声音播放
byte [] buffer = new byte[1024];
int len = 0;

try {
    ss = new ServerSocket(40050);
} catch (IOException e2) {
    // TODO Auto-generated catch block
    e2.printStackTrace();
    return;
}

InputStream ins = null;
while(true){

    try {
        s = ss.accept();
        Log.e("strat","ljq");
        ins = s.getInputStream();

        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        while( (len=ins.read(buffer)) != -1){
            outStream.write(buffer, 0, len);
        }
        ins.close();
        byte[] data = outStream.toByteArray();

        Message msg =handler.obtainMessage();
        msg.what = COMPLETED;
        msg.obj = data;
        handler.sendMessage(msg);

        outStream.flush();
        outStream.close();
        if(!s.isClosed()){
            s.close();
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return;
    }

}


class RMyHandler extends Handler {
@Override
public void handleMessage(Message msg){
if (msg.what == COMPLETED) {
try{

            byte[] tmpBuf  = (byte[])msg.obj;

            if(!isplay)
            {
                audioTrack.play();
                isplay=true;
            }


            //播放缓存区的数据
            audioTrack.write(tmpBuf, 0, tmpBuf.length);
            if(!isplay)
            {
            audioTrack.stop();
            audioTrack.release();
            }
         //   audioTrack = null;
            super.handleMessage(msg);

        }catch (Exception e)
        {
            Toast.makeText(RecordActivity.this,"语音播放失败", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }

    }
}

}

视频聊天可以演化成直播室形式,只不过只有一个人发送视频流和音频流,其他人则只是接收

第一次写技术博客,希望对大家有用,要完整源码也可以私聊小编
项目地址
https://download.csdn.net/download/zhongzhizhuo/12570465

http://m.ailiaw.top/#/
http://news.ailiaw.top/
————————————————
版权声明:本文为CSDN博主「zhongzhizhuo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhongzhizhuo/article/details/107081393

作者: 执着小钟

执着小钟

发表评论