Android通过WIFI建立热点,通过scoket实现聊天室,文件传输等通信功能。

来源:互联网 发布:钱箱软件 编辑:程序博客网 时间:2024/05/21 07:53

最近要做一个手机跟蓝牙模块进行通信的项目,查了一些资料,做出了一个可以实现通信的demo。

这里是把手机作为服务器,开启手机热点。(可以去系统设置里开启热点,也可以代码开启热点)

下面是开启热点的代码(配置文件要加上权限),但是这个方法在Android6.0里面开启不了,我查了一下大家都说加上

WRITE_SETTINGS权限,但是我加上了也不行,只有把
targetSdkVersion 由23改为22了。。。

  /**     * 判断WIFI热点是否开启     */    public boolean isApOn() {        try {            Method method = wifiManager.getClass().getDeclaredMethod("isWifiApEnabled");            method.setAccessible(true);            return (Boolean) method.invoke(wifiManager);        }        catch (Throwable ignored) {}        return false;    }    /**     * 设置热点名称及密码,并创建热点     * @param mSSID     * @param mPasswd     */    private Boolean stratWifiAp(String mSSID, String mPasswd,Boolean onoff) {        Method method1 = null;        if(onoff){            wifiManager.setWifiEnabled(false);        }       try {            //通过反射机制打开热点            method1 = wifiManager.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);            WifiConfiguration netConfig = new WifiConfiguration();            netConfig.SSID = mSSID;            netConfig.preSharedKey = mPasswd;            netConfig.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.RSN);            netConfig.allowedProtocols.set(WifiConfiguration.Protocol.WPA);            netConfig.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);            netConfig.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);            netConfig.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);            return (Boolean)method1.invoke(wifiManager, netConfig, onoff);        } catch (Exception e) {           return false;       }    }


打开后就可以启动服务起了


public void startServer(){    Thread thread = new Thread(){        @Override        public void run() {            super.run();                /*指明服务器端的端口号*/            try {                server = new ServerSocket(9999);            } catch (IOException e) {                e.printStackTrace();            }            while (true){                try {                    socket = server.accept();                    in  = socket.getInputStream();                    handler.sendEmptyMessage(2);                } catch (IOException e) {                    e.printStackTrace();                }                new ServerThread(socket,in).start();            }        }    };    thread.start();}    class ServerThread extends Thread{        private Socket socket;        private InputStream   inputStream;        public ServerThread(Socket socket,InputStream inputStream){            this.socket = socket;            this.inputStream = inputStream;        }        @Override        public void run() {            byte[]mode=new byte[13];//对话0  文件1            while (inputStream!= null) {                for(int i=0;i<13;i++){                    try {                        mode[i]=(byte)inputStream.read();                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                String modestr =new String(mode);                //传送的数据模式 0 对话  1 文件                try {                    //对话或文件                    int modeCode = Integer.parseInt(modestr.substring(0, 1), 10);                    //对话或文件大小                    long inLength = Long.parseLong(modestr.substring(1, 11), 10);                    //如果是文件的话文件名长度                    int nameLength = Integer.parseInt(modestr.substring(11, 13), 10);                    byte[] fileName = new byte[nameLength];                    byte[] mgs = new byte[new Long(inLength).intValue()];                    //设置buff缓存为512字节                    int inTime=(int)(inLength/512);                    int inTimeResidue=(int)(inLength%512);                    if (modeCode == 0) {                        for (int i = 0; i < inLength; i++) {                            try {                                mgs[i] = (byte) inputStream.read();                            } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                            }                        }                        reviceMgs = new String(mgs,"UTF-8");                        Log.e("收到数据", reviceMgs.toString());                        handler.sendEmptyMessage(1);                        //  ET_print.getText().append("\n"+new String(mgs));                    } else if (modeCode == 1) {                        for (int i = 0; i < nameLength; i++) {                            try {                                fileName[i] = (byte) inputStream.read();                            } catch (IOException e) {                                // TODO Auto-generated catch block                                e.printStackTrace();                            }                        }                        reviceName = new String(fileName,"UTF-8");                        Log.e("收到文件名", reviceName.toString());                     //   handler.sendEmptyMessage(1);                         dir = new File("/mnt/sdcard/WifiSocketDownload/"+reviceName);                        File file = new File("/mnt/sdcard/WifiSocketDownload");                        if (!file.exists()) {                            try {                                //按照指定的路径创建文件夹                                file.mkdirs();                                Log.e("创建文件夹成功",file.toString());                            } catch (Exception e) {                                // TODO: handle exception                                Log.e("创建文件夹失败","创建文件夹失败");                            }                        }                        if (!dir.exists()) {                            try {                                //在指定的文件夹中创建文件                                dir.createNewFile();                                Log.e("创建文件成功",dir.toString());                            } catch (Exception e) {                                Log.e("创建文件失败","创建文件失败");                            }                        }                    if(inTime>=0&&inTimeResidue>0) {                        byte[] buffer = new byte[512];                        reciveTime= 0;                        for (int i = 0; i < inTime + 1; i++) {                            for (int k = 0; k < 512; k++) {                                try {                                    buffer[k] = (byte) inputStream.read();                                } catch (IOException e) {                                    // TODO Auto-generated catch block                                    e.printStackTrace();                                }                            }                            writeFileSdcard(dir, buffer);                            handler.sendEmptyMessage(99);                        }                    }else if(inTime>=0&&inTimeResidue==0){                        byte[] buffer = new byte[512];                        reciveTime= 0;                        for (int i = 0; i < inTime ; i++) {                            for (int k = 0; k < 512; k++) {                                try {                                    buffer[k] = (byte) inputStream.read();                                } catch (IOException e) {                                    // TODO Auto-generated catch block                                    e.printStackTrace();                                }                            }                            writeFileSdcard(dir, buffer);                            handler.sendEmptyMessage(99);                        }                    }                        handler.sendEmptyMessage(98);                    }                }catch (Exception e){                }            }        }    }    public void writeFileSdcard(File fileName, byte []wb){        try{            //FileOutputStream fout = openFileOutput(fileName, MODE_PRIVATE);            FileOutputStream fout = new FileOutputStream(fileName,true);            fout.write(wb);            fout.close();        }        catch(Exception e){            e.printStackTrace();        }    }

while (true){    try {        socket = server.accept();        in  = socket.getInputStream();        handler.sendEmptyMessage(2);    } catch (IOException e) {        e.printStackTrace();    }    new ServerThread(socket,in).start();}


当有客户端连接进来,就启动一个线程
 new ServerThread(socket,in).start();
进行监听

(如果要实现多人群聊的话,就是美有一个客户端进行连接,就把这个客户端保存到list里面然后服务器进行数据转发,我这里没有保存,也没有关闭前一个客户端,如果有两个客户端进行连接的话,服务器发的对话只能最近一个客户端可以收到,但是客户端发给服务器的数据,服务器都能收到)


ServerThread的run方法里对接收到的数据进行处理

byte[]mode=new byte[13];
13个字节为发送过来的头部分,其中第一个字节判断是发送的对话还是文件,第二到11共10字节为发送类容的字节数(比如163字节的类容就表示为0000000163)(好像最大可以是9个多G的样子,一般用不到这么长啦),11到13字节表示文件名长度,如果是对话就是00.
for(int i=0;i<13;i++){    try {        mode[i]=(byte)inputStream.read();    } catch (IOException e) {        // TODO Auto-generated catch block        e.printStackTrace();    }}
读出13字节的头
//对话或文件int modeCode = Integer.parseInt(modestr.substring(0, 1), 10);//对话或文件大小long inLength = Long.parseLong(modestr.substring(1, 11), 10);//如果是文件的话文件名长度int nameLength = Integer.parseInt(modestr.substring(11, 13), 10);byte[] fileName = new byte[nameLength];byte[] mgs = new byte[new Long(inLength).intValue()];

对头进行解析 (文件和对话分别处理)


下面是服务器发给客户端发送对话的方法(没有加发送文件,客户端有发送文件,如果服务器要向客户端发送文件,可以用客户端发送文件的方法)

public static Boolean send(Socket socket, byte[] msg) {        DataOutputStream out=null;        try {            out = new DataOutputStream((socket.getOutputStream()));            String mode ="0";            String name ="00";            int mgsLength =msg.length;            String ll =String.format("%010d", mgsLength);            String sss=mode+ll+name;            byte sendByte[] =addBytes(sss.getBytes("UTF-8"),msg);            Log.e("aa","类容字节"+ Arrays.toString(sendByte));            out.write(sendByte);            System.out.println("写入数据");            return true;            //  out.flush();        } catch (IOException e) {            e.printStackTrace();            System.out.println("写入数据异常");            return false;        }    }    public static byte[] addBytes(byte[] data1, byte[] data2) {        byte[] data3 = new byte[data1.length + data2.length];        System.arraycopy(data1, 0, data3, 0, data1.length);        System.arraycopy(data2, 0, data3, data1.length, data2.length);        return data3;    }



下面是服务器的部分 

if (!wifiManager.isWifiEnabled()) {    wifiManager.setWifiEnabled(true);}

WifiConfiguration config = new WifiConfiguration();config.SSID = "\"wifisocket\"";config.preSharedKey = "\"00000000\"";//加密wificonfig.hiddenSSID = true;config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);//config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);config.status = WifiConfiguration.Status.ENABLED;int netId = wifiManager.addNetwork(config);

上面是打开WiFi 连接服务WiFi热点的代码


连接上服务器热点后,启动客户端连接服务器:

    public void initClientSocket() {        try {            socket = new Socket("192.168.43.1", 9999);            handler.sendEmptyMessage(1);        } catch (UnknownHostException e) {            // TODO Auto-generated catch block            System.out.println("请检查端口号是否为服务器IP");            handler.sendEmptyMessage(5);            e.printStackTrace();        } catch (IOException e) {            // TODO Auto-generated catch block            System.out.println("服务器未开启");            handler.sendEmptyMessage(5);            e.printStackTrace();        }    }

读取服务器信息线程

    private class ReadThread extends Thread{        @Override        public void run() {            byte[]mode=new byte[13];//对话0  文件1            InputStream inputStream  = null;            try {                inputStream = socket.getInputStream();            } catch (IOException e) {                e.printStackTrace();            }            while (inputStream!= null) {                for(int i=0;i<13;i++){                    try {                        mode[i]=(byte)inputStream.read();                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();//                        try {//                            Log.e("关闭socket"," socket.close();");//                            inputStream.close();//                            socket.close();//                        } catch (IOException e1) {//                            e1.printStackTrace();//                        }                    }                }                String modestr =new String(mode);                //传送的数据模式 0 对话  1 文件                try{                int modeCode=Integer.parseInt(modestr.substring(0,1), 10);                //对话或文件大小                int inLength=Integer.parseInt(modestr.substring(1,11), 10);                //如果是文件的话文件名长度                int nameLength=Integer.parseInt(modestr.substring(11,13), 10);                byte[]fileName=new byte[nameLength];                byte[]mgs=new byte[inLength];                for(int i=0;i<inLength;i++){                    try {                        mgs[i]=(byte)inputStream.read();                    } catch (IOException e) {                        // TODO Auto-generated catch block                        e.printStackTrace();                    }                }                if(modeCode==0){                    reviceMgs=new String(mgs,"UTF-8");                    Log.e("收到数据",reviceMgs.toString());                    handler.sendEmptyMessage(3);                    //  ET_print.getText().append("\n"+new String(mgs));                }else if (modeCode==1){                }                }catch (Exception e){                }            }        }    }

我们可以设置一个按钮,点击按钮就连接服务器启动线程

就可以在点击时执行

new Thread(runnable).start();//开启线程


Runnable runnable = new Runnable() {    @Override    public void run() {        // TODO Auto-generated method stub        initClientSocket();        readThread = new ReadThread();        readThread.start();    }};


下面是像服务器发送对话和文件的方法(发送文件前要选着一个文件路径)

    public static byte[] addBytes(byte[] data1, byte[] data2) {        byte[] data3 = new byte[data1.length + data2.length];        System.arraycopy(data1, 0, data3, 0, data1.length);        System.arraycopy(data2, 0, data3, data1.length, data2.length);        return data3;    }    public static Boolean send(Socket socket, byte[] msg) {        DataOutputStream out=null;        try {            out = new DataOutputStream((socket.getOutputStream()));            String mode ="0";            String name ="00";            int mgsLength =msg.length;            String ll =String.format("%010d", mgsLength);            String sss=mode+ll+name;            byte sendByte[] =addBytes(sss.getBytes("UTF-8"),msg);            Log.e("aa","类容字节"+ Arrays.toString(sendByte));            out.write(sendByte);            System.out.println("写入数据");            return true;            //  out.flush();        } catch (IOException e) {            e.printStackTrace();            System.out.println("写入数据异常");            return false;        }    }    public  Boolean sendfile(Socket socket) {        DataOutputStream out=null;        try {            out = new DataOutputStream((socket.getOutputStream()));            String mode ="1";            String[] getname = file_path.split("/");            String filename=getname[getname.length-1];            byte filenamebyte[] =filename.getBytes("UTF-8");            String name =String.format("%02d", filenamebyte.length);            File file =new File(file_path);            if (file.exists()) {                sendtime=0;                FileInputStream fis = null;                fis = new FileInputStream(file);                size = fis.available();                String filesizeString =String.format("%010d", size);                String sss=mode+filesizeString+name;                byte sendByteHead[] =addBytes(sss.getBytes("UTF-8"),filenamebyte);                out.write(sendByteHead);                handler.sendEmptyMessage(91);                int n=512;                byte buffer[]=new byte[n];                while((fis.read(buffer,0,n)!=-1)&&(n>0)){                    System.out.println(Arrays.toString(buffer));                    System.out.println(new String(buffer));                    out.write(buffer);                    handler.sendEmptyMessage(92);                }                System.out.println("写入完成");                handler.sendEmptyMessage(93);                fis.close();                return true;            } else {                file.createNewFile();                Log.e("获取文件大小", "文件不存在!");                return false;            }            //  out.flush();        } catch (IOException e) {            e.printStackTrace();            System.out.println("写入数据异常");            return false;        }    }


源码下载地址:点击打开链接

如果改下包名安装成2个APP,同一个手机也可以同时启动服务器和客户端,下图就是同一pad上进行通信的截图。






1 0
原创粉丝点击