Android如何实现茄子快传
茄子快传是一款文件传输应用,相信大家都很熟悉这款应用,应该很多人用过用来文件的传输。它有两个核心的功能:
端到端的文件传输
Web端的文件传输
这两个核心的功能我们具体来分析一下!
端到端的文件传输
所谓的端到端的文件传输是指应用端发送到应用端(这里的应用端指Android应用端),这种文件传输方式是文件发送端和文件接收端必须安装应用。
效果图
文件发送方
文件发送方_1
文件发送方_2
文件发送方_3
文件接收方
文件接收方_1
文件接收方_2
简单的文件传输的话,我们可以用蓝牙,wifi直连,ftp这几种方式来进行文件的传输。但是:
蓝牙传输的话,速度太慢,而且要配对。相对比较麻烦。
wifi直连差不多跟蓝牙一样,但是速率很快,也要配对。
ftp可以实现文件的批量传输,但是没有文件的缩略图。
最初分析这个项目的时候就想着通过自定义协议的Socket的通信来实现,自定义的协议包括header + body的自定义协议, header部分包括了文件的信息(长度,大小,文件路径,缩略图), body部分就是文件。现在实现这一功能。(后序:后面开发《网页传》功能的时候,可以考虑这两个核心的功能都能用在Android架设微型Http服务器来实现。这是后话了。)
流程图
端到端的流程图
编码实现
两部设备文件传输是需要在一个局域网的条件下的,只有文件发送方连接上文件接收方的热点(搭建了一个局域网),这样文件发送方和文件接收方就在一个局域网里面,我们才可以进行Socket通信。这是一个大前提!
初始化条件 -- Ap(热点)和Wifi的管理, 文件的扫描
对Android的Ap(热点)和Wifi的一些操作都封装在下面两个类:
关于热点和Wifi的操作都是根据WifiManager来操作的。所以要像操作WifiManeger是必须要一些权限的。必须在AndroidManifest.xml清单文件里面声明权限:
文件接收端打开热点并且配置热点的代码:
//1.初始化热点
WifiMgr.getInstance(getContext()).disableWifi();
if(ApMgr.isApOn(getContext())){
ApMgr.disableAp(getContext());
}
//热点相关的广播
mWifiAPBroadcastReceiver = new WifiAPBroadcastReceiver() {
@Override
public void onWifiApEnabled() {
Log.i(TAG, "======>>>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() {
@Override
public 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 :boolean
String 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 getSpecificTypeFiles(Context context, String[] extension){
List fileInfoList = new ArrayList();
//内存卡文件的Uri
Uri fileUri= MediaStore.Files.getContentUri("external");
//筛选列,这里只筛选了:文件路径和含后缀的文件名
String[] projection=new String[]{
MediaStore.Files.FileColumns.DATA, MediaStore.Files.FileColumns.TITLE
};
//构造筛选条件语句
String selection="";
for(int i=0;i
{
if(i!=0)
{
selection=selection+" OR ";