android 使用asmack库进行文件收发
来源:互联网 发布:网络教育概念股 编辑:程序博客网 时间:2024/06/13 07:11
网友 t8500071说asmack有更新了,去http://code.google.com/p/asmack/看了下,现在代码转到 https://github.com/Flowdalic/asmack
所以大家可以直接去下官方的测试,下面的没啥用了。。
之前记录了部分的怎么用smack进行连接、登录、聊天等等,这边就接着说文件传输,看官方的文档,
http://www.igniterealtime.org/builds/smack/docs/latest/documentation/extensions/index.html
看完文档你会觉得好简单呐,不过要操作起来真的挺要命的,至少我挺纠结的。
先说步骤
1、创建一个文件传输管理的类
// Create the file transfer manager FileTransferManager manager = new FileTransferManager(connection);2、从这个管理类创建一个向 特定用户 发送文件的输出类
// Create the outgoing file transfer OutgoingFileTransfer transfer = manager.createOutgoingFileTransfer("romeo@montague.net"); //这边用户要为 完整的jid,user@servername/resource // Send the file transfer.sendFile(new File("shakespeare_complete_works.txt"), "You won't believe this!");3、接收文件即直接加个监听器
// Create the listener manager.addFileTransferListener(new FileTransferListener() { public void fileTransferRequest(FileTransferRequest request) { // Check to see if the request should be accepted if(shouldAccept(request)) { // Accept it IncomingFileTransfer transfer = request.accept(); transfer.recieveFile(new File("shakespeare_complete_works.txt")); } else { // Reject it request.reject(); // 拒绝接收文件。 } } });4、查看文件收发的状态
while(!transfer.isDone()) { //可以直接加到 transfer.sendFile 或者 transfer.recieveFile 后面。 if(transfer.getStatus().equals(Status.ERROR)) { System.out.println("ERROR!!! " + transfer.getError()); } else { System.out.println(transfer.getStatus()); System.out.println(transfer.getProgress()); } sleep(1000); }
如果是smack在Pc运行的话,服务器配置没问题,一般就没问题了。<1>
我这边的库可以了,我会上传供大家测试哈。
在文件传输这个环节,服务器的配置挺还是很重要的,因为文件传输使用到了两种协议,IBB协议和S5B协议,协议介绍看这里。
其中在文件传输过程中,由更顶层协议去裁判,是否传输文件,如果是则使用哪种协议进行传输,(如果S5B可用,默认S5B),我使用的这个库也是这样。我尝试过很多版本的asmack库,都不行,衰人一个啊。后面就还是慢慢来吧,看下源码好了。我说下我遇到情况。
出现错误且里面 有说到<streamhost jid="myid@mydomain.com/smack" host="127.0.0.1" port="7777"/>,就是asmack库里面的一个函数错了,直接返回127.0.0.1这个IP,修改org.jivesoftware.smackx.filetransfer.Socks5TransferNegotiator中的函数:
private String discoverLocalIP() throws UnknownHostException {try {for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {NetworkInterface intf = en.nextElement();for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {InetAddress inetAddress = enumIpAddr.nextElement();if (!inetAddress.isLoopbackAddress()) {return inetAddress.getHostAddress().toString();}}}} catch (SocketException ex) {Logger.error("Error retrieving the local IP", ex);}throw new UnknownHostException("Failed to retrieve local IP"); //return InetAddress.getLocalHost().getHostAddress(); //注释掉原本的代码 }这样保证返回的android机子的ip不是127.0.0.1。
因为在S5B协议里面,有一个<streamhost host="" jid="" port="" />的元素,这个是用于告诉对方本机可以用于建立文件传输的stream流的host,如果你发送了一个host为127.0.0.1的话,那对方在判断这个地址的时候,会误判为可以用(应该是这个地址是特殊地址,本地回路嘛),然后对方会回复一个result给你告诉你他那边确认OK,然后这个时候,不论是你还对方,都无法把stream流建立起来的。所以上面就是为了屏蔽127.0.0.1,获得真实的本地IP。
上面的解决办法是可以行的。不过还有一种方法就是直接不让你这个客户端找到本地ip,这样你这边就没有<streamhost host="" jid="" port="" />这个东西了,你就会去向服务器请求,查询服务器的代理,一般会有一个proxy.server-name这样的一个代理,这个代理的ip來至哪里?看openfire服务器,你很容易可以发现,服务器的server-name就是你的计算机名字,在/etc/hosts里面添加你的当前PC的IP和计算机名,之后重启服务器,服务器就会将server-name绑定到当前的IP上,proxy.your-openfire-host这个代理的IP跟服务器的IP一样,这样客服端就可以找到proxy.server-name代理的IP,之后两个客服端就会建立一个用使用代理而建立起来的stream流,然后开始传输文件。
当然,上面的方法还是挺OK的,不过我还发现了一个方法,其实也就是在你不让客服端不发现的本地IP和proxy.server-name所对应的IP为NULL的时候,客户端会放弃使用S5B,而使用IBB,这个使用协议是默认的,名字翻译过来就是带内字节流,带内?带内我个人理解是把要发送的文件分割,然后放在packet里面进行传输,而不像S5B那样再建立一个stream流。如果你用IBB发送文件的时候,你打开DEBUG,你就可以在发送的packet里面看到一堆被格式化过的文字,那些就是被传输文件的数据啦。
我自己改的 asmack :http://download.csdn.net/detail/shmcclmm/5046135
我修改的是 org.jivesoftware.smackx/bytestreams/Socks5BytestreamManager.java 这个文件
- android 使用asmack库进行文件收发
- 解决asmack在android上收发文件的negotiating stream问题
- Android asmack使用介绍
- Android asmack使用介绍
- Android asmack使用介绍
- Android asmack使用介绍
- Android asmack使用介绍
- Android asmack使用介绍
- Android之asmack使用介绍
- aSmack 使用
- Android端使用asmack实现IM
- android 使用javamail收发邮件
- android使用文件进行存储
- Android 即时通讯开发——asmack jar包使用
- android asmack 接受消息
- 在 Android 的 IM 应用中使用 asmack 库实现用户头像的传输(基于VCard协议)
- Android下Socket收发文件初探
- 使用TCPServer与TCPClient收发文件--转贴
- linux嵌入式开发之挂载网络文件系统
- VC中实现带有背景位图的树型控件
- 用DirectDraw实现的渐入渐出效果
- 判断当前显示是否为桌面
- struts2处理.do后缀的请求
- android 使用asmack库进行文件收发
- 各种在线工具集
- Java RMI
- jdk1.7的新特性
- JVM
- linux 内核驱动编程 简单例子 与_IO, _IOR, _IOW, _IOWR 宏解析
- java web开发 购物车功能实现
- android java获取当前时间的总结
- 如何使用Proxy模式及Java内建的动态代理机制