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
- Android通过WIFI建立热点,通过scoket实现聊天室,文件传输等通信功能。
- 通过笔记本建立wifi热点
- 通过 cmd 建立wifi 热点
- android通过手机热点通信
- android 通过wifi 热点实现手机摄像头数据共享
- 笔记本wifi做热点 android通过热点上网
- android wifi热点的创建以及连接通信(华为T8951 Google GALAXY Nexus 测试通过)
- 通过WifiManager可以实现对wifi进行操作,实现wifi自动连接等一些功能
- Android中通过socket建立长连接实现推送功能
- android 热点开发、WiFi热点通信
- android手机wifi热点通信
- 通过Socket实现文件传输(Java)
- iPhone建立热点-通过USB连接
- websocket实现聊天室等功能
- 通过wifi与设备进行通信(Android)
- android手机通过WIFI与硬件进行通信
- android开发步步为营之48:通过WifiManager自动连上某个wifi热点
- android通过反射获取wifi热点ap的ssid和password
- react-native ViewPageAndroid页面跳转问题
- 【J2EE】学习环境配置
- TabLayout实现底部顶部导航栏
- Laravel5.4常见问题-Migrate数据库问题
- Java读取Excel表格数据的基本步骤
- Android通过WIFI建立热点,通过scoket实现聊天室,文件传输等通信功能。
- ajax股票获取
- 蓝桥杯 方格填数(DFS)
- iWatch开发:实现iWatch 与 iPhone 之间数据发送与接收
- -04-LVDS输入接口设计【Xilinx-LVDS读写功能实现】
- jQuery AJAX 方法 success()后台传来的4种数据
- Oracle 约束的定义
- windown git安装
- 分布式日志收集并统计分析