Android仿茄子快传-实现面对面快传功能

news/2025/2/5 22:45:59/

茄子快传是一款文件传输应用,相信大家都很熟悉这款应用,应该很多人用过用来文件的传输。
它有两个核心的功能:

端到端的文件传输
Web端的文件传输

这两个核心的功能我们具体来分析一下!

  • 端到端的文件传输

    所谓的端到端的文件传输是指应用端发送到应用端(这里的应用端指Android应用端),
    这种文件传输方式是文件发送端和文件接收端必须安装应用。

    效果图

文件发送方

这里写图片描述

这里写图片描述

这里写图片描述

文件接收方

这里写图片描述

这里写图片描述

简单的文件传输的话,我们可以用蓝牙,wifi直连,ftp这几种方式来进行文件的传输。但是:

蓝牙传输的话,速度太慢,而且要配对。相对比较麻烦。
wifi直连差不多跟蓝牙一样,但是速率很快,也要配对。
ftp可以实现文件的批量传输,但是没有文件的缩略图。

最初分析这个项目的时候就想着通过自定义协议的Socket的通信来实现,自定义的协议包括
header + body的自定义协议, header部分包括了文件的信息(长度,大小,文件路径,
缩略图), body部分就是文件。现在实现这一功能。(后序:后面开发《网页传》功能的时候,
可以考虑这两个核心的功能都能用在Android架设微型Http服务器来实现。这是后话了。)

  • 端到端流程图

这里写图片描述

  • 编码实现

两部设备文件传输是需要在一个局域网的条件下的,只有文件发送方连接上文件接收方的热点(搭建了一个局域网),
这样文件发送方和文件接收方就在一个局域网里面,我们才可以进行Socket通信。这是一个大前提!

初始化条件 – Ap(热点)和Wifi的管理, 文件的扫描
对Android的Ap(热点)和Wifi的一些操作都封装在下面两个类:

1.https://github.com/mayubao/KuaiChuan/blob/master/app/src/main/java/io/github/mayubao/kuaichuan/core/utils/WifiMgr.java
2.https://github.com/mayubao/KuaiChuan/blob/master/app/src/main/java/io/github/mayubao/kuaichuan/core/utils/ApMgr.java

关于热点和Wifi的操作都是根据WifiManager来操作的。

所以要像操作WifiManeger是必须要一些权限的。必须在AndroidManifest.xml清单文件里面声明权限:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

文件接收端打开热点并且配置热点的代码:

 //1.初始化热点WifiMgr.getInstance(getContext()).disableWifi();if(ApMgr.isApOn(getContext())){ApMgr.disableAp(getContext());}mWifiAPBroadcastReceiver = new WifiAPBroadcastReceiver() {@Overridepublic void onWifiApEnabled() {if(!mIsInitialized){mUdpServerRuannable = createSendMsgToFileSenderRunnable();AppContext.MAIN_EXECUTOR.execute(mUdpServerRuannable);mIsInitialized = true;tv_desc.setText(getResources().getString(R.string.tip_now_init_is_finish));tv_desc.postDelayed(new Runnable() {@Overridepublic void run() {tv_desc.setText(getResources().getString(R.string.tip_is_waitting_connect));}}, 2*1000);}}};IntentFilter filter = new IntentFilter(WifiAPBroadcastReceiver.ACTION_WIFI_AP_STATE_CHANGED);registerReceiver(mWifiAPBroadcastReceiver, filter);ApMgr.isApOn(getContext()); // check Ap state :booleanString ssid = TextUtils.isNullOrBlank(android.os.Build.DEVICE) ? Constant.DEFAULT_SSID : android.os.Build.DEVICE;ApMgr.configApState(getContext(), ssid); // change Ap state :boolean

对于类WifiAPBroadcastReceiver是热点的一个广播类,最后一行代码是配置指定名称的热点,
这里是以设备名称作为热点的名称。

文件发送端发送文件,文件发送端首先要选择要发送的文件,然后将要选择的文件存储起来,
这里我是用了一个HashMap将发送的文件存储起来,key是文件的路径,value是FileInfo对象。

以下是扫描手机存储盘上面的文件列表的代码:

/*** 存储卡获取 指定文件* @param context* @param extension* @return*/public static List<FileInfo> getSpecificTypeFiles(Context context, String[] extension){List<FileInfo> fileInfoList = new ArrayList<FileInfo>();//内存卡文件的UriUri fileUri= MediaStore.Files.getContentUri("external");//筛选列,这里只筛选了:文件路径和含后缀的文件名String[] projection=new String[]{MediaStore.Files.FileColumns.DATA, MediaStore.Files.FileColumns.TITLE};//构造筛选条件语句String selection="";for(int i=0;i<extension.length;i++){if(i!=0){selection=selection+" OR ";}selection=selection+ MediaStore.Files.FileColumns.DATA+" LIKE '%"+extension[i]+"'";}//按时间降序条件String sortOrder = MediaStore.Files.FileColumns.DATE_MODIFIED;Cursor cursor = context.getContentResolver().query(fileUri, projection, selection, null, sortOrder);if(cursor != null){while (cursor.moveToNext()){try{String data = cursor.getString(0);FileInfo fileInfo = new FileInfo();fileInfo.setFilePath(data);long size = 0;try{File file = new File(data);size = file.length();fileInfo.setSize(size);}catch(Exception e){}fileInfoList.add(fileInfo);}catch (Exception e){Log.i("FileUtils", "------>>>" + e.getMessage());}}}Log.i(TAG, "getSize ===>>> " + fileInfoList.size());return fileInfoList;}
注意**:这里扫描的FileInfo对象只是扫描了文件路径filePath, 还有文件的大小size。
FileInfo的其他属性到文件传输的时候再二次获取,
获取FileInfo的其他属性都在FileUtils这个工具类里面了。

文件发送端打开wifi扫描热点并且连接热点的代码:

/*** 初始化*/private void init(){radarScanView.startScan();//        if(WifiMgr.getInstance(getContext()).isWifiEnable()){//wifi打开的情况
//        }else{//wifi关闭的情况
//            WifiMgr.getInstance(getContext()).openWifi();
//        }if(!WifiMgr.getInstance(getContext()).isWifiEnable()) {//wifi未打开的情况WifiMgr.getInstance(getContext()).openWifi();}getOrUpdateWifiScanResult();mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TO_SHOW_SCAN_RESULT), 1000);}/*** 获取或者更新wifi扫描列表*/private void getOrUpdateWifiScanResult(){WifiMgr.getInstance(getContext()).startScan();mScanResultList = WifiMgr.getInstance(getContext()).getScanResultList();mScanResultList = ListUtils.filterWithNoPassword(mScanResultList);if(mScanResultList != null){mWifiScanResultAdapter = new WifiScanResultAdapter(getContext(),mScanResultList);lv_result.setAdapter(mWifiScanResultAdapter);lv_result.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//TODO 进入文件传输部分ScanResult scanResult = mScanResultList.get(position);Log.i(TAG, "###select the wifi info ======>>>" + scanResult.toString());//1.连接网络String ssid = Constant.DEFAULT_SSID;ssid = scanResult.SSID;WifiMgr.getInstance(getContext()).openWifi();WifiMgr.getInstance(getContext()).addNetwork(WifiMgr.createWifiCfg(ssid, null, WifiMgr.WIFICIPHER_NOPASS));//2.发送UDP通知信息到 文件接收方 开启ServerSocketRunnablemUdpServerRuannable = createSendMsgToServerRunnable(WifiMgr.getInstance(getContext()).getIpAddressFromHotspot());AppContext.MAIN_EXECUTOR.execute(mUdpServerRuannable);}});}}
对于ListUtils.filterWithNoPassword是将扫描的结果进行过滤,过滤掉有密码的扫描结果。lv_result.setOnItemClickListener回调的方法是连接指定的热点来形成一个局域网。
文件传输的大前提条件就已经形成了。到这里文件发送端和文件接收端的初始化环境也就搭建起来了。
  • 文件传输模块

    文件传输模块的核心代码就只有4个类,Transferable, BaseTransfer, FileSender, FileReceiver。
    

    Transferable是接口。
    BaseTransfer, FileSender, FileReceiver是类。
    对于文件发送端,每一个文件发送对应一个FileSender,而对于文件接收端,
    每一个文件的接收对应一个FileReceiver。
    而FileSender,FileReceiver是继承自 抽象类BaseTransfer的。 BaseTransfer是实现了Transferable接口。

下面是4个类图的关系:

这里写图片描述

在Transferable接口中定义了4个方法,分别是初始化,解析头部,解析主体,结束。
解析头部和解析主体分别对应上面说的自定义协议的header和body。
初始化是为每一次文件传输做初始化工作,而结束是为每一次文件传输做结束工作,
比如关闭一些资源流,Socket等等。而BaseTransfer就只是实现了Transferable, 里面封装了一些常量。
没有实现具体的方法,具体的实现是FileSender,FileReceiver。

代码详情:

1.https://github.com/mayubao/KuaiChuan/blob/master/app/src/main/java/io/github/mayubao/kuaichuan/core/Transferable.java

2.https://github.com/mayubao/KuaiChuan/blob/master/app/src/main/java/io/github/mayubao/kuaichuan/core/BaseTransfer.java

3.https://github.com/mayubao/KuaiChuan/blob/master/app/src/main/java/io/github/mayubao/kuaichuan/core/FileSender.java

4.https://github.com/mayubao/KuaiChuan/blob/master/app/src/main/java/io/github/mayubao/kuaichuan/core/FileReceiver.java

总结

端到端的文件传输就分析到这里,主要是Ap热点的操作,Wifi的操作,Socket通信来实现文件的传输。
但是这里的Socket用到的不是异步IO,是同步IO。所以会引起阻塞。
比如在FileSender中的暂停文件传输pause方法调用之后,会引起FileReceiver中文件传输的阻塞。
如果你对异步IO有兴趣,你也可以去实现一下。

对于端对端的核心代码都是在 io.github.mayubao.kuaichuan.core 包下面。
这是我在github上面的项目链接
https://github.com/mayubao/KuaiChuan

原网址:http://blog.csdn.net/yubaoma2014


http://www.ppmy.cn/news/912637.html

相关文章

如何打造 茄子快传 这样一款文件传输应用

打造茄子快传文件Android端传输应用 效果图 主界面文件发送方文件接收方网页传20161218新增 实现原理流程图分析实现过程项目地址测试版本 v10v11 如何打造茄子快传这样一款 零耗流量的文件传输应用&#xff1f; 打造茄子快传文件Android端传输应用 效果图 主界面 文件发送…

从”茄子快传”看应用程序如何获取手机已安装程序的apk文件

”茄子快传”是联想开发的一款近距离文件共享软件&#xff0c;它通过wifi-direct(速度飞快,不需要联网)或者普通的网络(速度慢)在不同手机间传递文件。不知为何&#xff0c;它就火了起来&#xff0c;火的也飞快。其中&#xff0c;共享传输已安装程序文件apk这一功能引起了我强烈…

Android如何实现茄子快传

Android如何实现茄子快传 茄子快传是一款文件传输应用&#xff0c;相信大家都很熟悉这款应用&#xff0c;应该很多人用过用来文件的传输。它有两个核心的功能&#xff1a; 端到端的文件传输Web端的文件传输 这两个核心的功能我们具体来分析一下&#xff01; 端到端的文件传…

低调的移动互联网出海之王——「茄子快传」成长简史

谈及移动互联网的发展历程&#xff0c;中国可以算作是起步晚、但后来居上的。近几年随着国内互联网市场竞争的加剧&#xff0c;越来越多的公司开始放眼全球&#xff0c;试图在海外市场上分得一杯羹。 出海繁星中最耀眼的那颗当属「茄子快传」了&#xff08;海外版命名Shareit&a…

WPF Prims框架详解

文章目录 前言Prism基本使用Prism选择&#xff0c;DryIoc还是UnityPrism基本框架搭建Prism动态更新View和ViewModel对应关系参数动态更新函数动态绑定 prism新建项目模板region使用事例测试是否限制空间 消息订阅如何使用消息订阅使用建议 路由导航对话框/弹窗功能实现代码 前言…

三分钟了解Redis HyperLogLog 数据结构

文章目录 0. 前言1. 原理1.2 原理解析 2.实战案例3. Redis从入门到精通系列文章4. 常见问题4.1. 什么是Redis HyperLogLog&#xff1f;4.2. HyperLogLog算法的核心思想是什么&#xff1f;4.3. HyperLogLog算法的误差率如何控制&#xff1f;4.4. HyperLogLog算法的存储空间大小与…

复制iPhone端百度网盘下载好的视频到电脑(Mac / Windows)- iOS 12.4

吐槽 以前下载的东西还能通过iTools&#xff0c;iTunes等直接复制到电脑&#xff0c;现在竟然都不行了&#xff0c;iOS想干啥。 其实问题的关键是&#xff1a;云盘不支持“iTunes File Sharing”文件共享功能了。 解决办法 电脑装好爱思助手手机装好暴风影音iPhone打开“百度…

linux咪咕视频,咪咕视频电脑版

一个视频软件的电脑版对我们来说有多重要&#xff1f;当然很重要&#xff01;对于拥有2018世界杯64场真直播的咪咕视频&#xff0c;虽然官方并没有正式推出PC端软件&#xff0c;但还是有很多诀窍和办法可以获得我们自己的咪咕视频电脑版。有了一个方便的电脑版&#xff0c;可以…