概述
后来优化了代码,完整项目博客地址:这里太久了
https://blog.csdn.net/fkgjdkblxckvbxbgb/article/details/79456563
项目中有集成tecent 的Im, 传递一些图片 ,音频和一些文字消息,还是刚刚的 ,还是系统升级的问题 ,OTA升级没做好,只能升级系统整包 ,600多M ,网络不好的用户就很头疼,文件太大 ,耗时太久 ,
这就催生了我是用局域网文件传输的功能 ,上次想到的是UDP ,测试环境下 ,丢包比较严重 ,体验较差,返回来使用Socket传输把 ,稳定性提高了很多
这是网上以为仁兄的代码 ,我稍微改动了一下 ,写下来分享出来,网上很多的博客 ,demo都美发使用,这个是可以使用的
直接上代码
选择本地文件并上传需要依赖
compile 'com.nononsenseapps:filepicker:2.5.2'
清单文件注册
<activity android:name="com.nononsenseapps.filepicker.FilePickerActivity" android:label="@string/app_name" android:theme="@style/FilePickerTheme"> <intent-filter> <action android:name="android.intent.action.GET_CONTENT" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
1:一个封装进度的对象
package com.mmb.tcp; /** * Created by jsjm on 2017/11/28. */ public class TcpEntity { long progress; public TcpEntity(long progress) { this.progress = progress; } public long getProgress() { return progress; } public void setProgress(long progress) { this.progress = progress; } }
工具类,所有的传送和接受代码就在这里了
package com.mmb.tcp; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.util.Log; import org.greenrobot.eventbus.EventBus; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; public class SocketManager { private ServerSocket server; private Handler handler = null; public SocketManager(Handler handler) { this.handler = handler; int port = 9999; while (port > 9000) { try { server = new ServerSocket(port); break; } catch (Exception e) { port--; } } SendMessage(1, port); Thread receiveFileThread = new Thread(new Runnable() { @Override public void run() { while (true) { ReceiveFile(); } } }); receiveFileThread.start(); } void SendMessage(int what, Object obj) { if (handler != null) { Message.obtain(handler, what, obj).sendToTarget(); } } void ReceiveFile() { try { Socket name = server.accept(); InputStream nameStream = name.getInputStream(); InputStreamReader streamReader = new InputStreamReader(nameStream); BufferedReader br = new BufferedReader(streamReader); String fileName = br.readLine(); br.close(); streamReader.close(); nameStream.close(); name.close(); SendMessage(0, "正在接收:" + fileName); Socket data = server.accept(); InputStream dataStream = data.getInputStream(); String savePath = Environment.getExternalStorageDirectory().getPath() + "/" + fileName; FileOutputStream file = new FileOutputStream(savePath, false); byte[] buffer = new byte[1024]; int size = -1; while ((size = dataStream.read(buffer)) != -1) { file.write(buffer, 0, size); } file.close(); dataStream.close(); data.close(); SendMessage(0, fileName + "接收完成"); } catch (Exception e) { SendMessage(0, "接收错误:n" + e.getMessage()); } } public void SendFile(ArrayList<String> fileName, ArrayList<String> path, String ipAddress, int port) { try { for (int i = 0; i < fileName.size(); i++) { Socket name = new Socket(ipAddress, port); OutputStream outputName = name.getOutputStream(); OutputStreamWriter outputWriter = new OutputStreamWriter(outputName); BufferedWriter bwName = new BufferedWriter(outputWriter); bwName.write(fileName.get(i)); bwName.close(); outputWriter.close(); outputName.close(); name.close(); SendMessage(0, "正在发送" + fileName.get(i)); Socket data = new Socket(ipAddress, port); OutputStream outputData = data.getOutputStream(); FileInputStream fileInput = new FileInputStream(path.get(i)); int size = -1; long sum = 0; byte[] buffer = new byte[1024]; while ((size = fileInput.read(buffer, 0, 1024)) != -1) { outputData.write(buffer, 0, size); sum += buffer.length; Log.e("write", "====" + sum); EventBus.getDefault().post(new TcpEntity(sum)); } outputData.close(); fileInput.close(); data.close(); SendMessage(0, fileName.get(i) + " 发送完成"); } SendMessage(0, "所有文件发送完成"); } catch (Exception e) { SendMessage(0, "发送错误:n" + e.getMessage()); } } }
传送端的代码
package com.mmb.activity; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; import android.content.ClipData; import android.content.Intent; import android.net.Uri; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.mmb.tcp.SocketManager; import com.mmb.tcp.TcpEntity; import com.nononsenseapps.filepicker.FilePickerActivity; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; public class ChatTestActivity extends AppCompatActivity { private static final int FILE_CODE = 0; private TextView tvMsg, send_progress; private EditText txtIP, txtEt; private Button btnSend; private Handler handler; private SocketManager socketManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_chat_test); initView(); EventBus.getDefault().register(this); } private void initView() { send_progress = (TextView) findViewById(R.id.send_progress); tvMsg = (TextView) findViewById(R.id.tvMsg); txtIP = (EditText) findViewById(R.id.txtIP); txtEt = (EditText) findViewById(R.id.et); btnSend = (Button) findViewById(R.id.btnSend); btnSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent i = new Intent(ChatTestActivity.this, FilePickerActivity.class); i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, true); i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, false); i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_FILE); i.putExtra(FilePickerActivity.EXTRA_START_PATH, Environment.getExternalStorageDirectory().getPath()); startActivityForResult(i, FILE_CODE); } }); handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0: SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); txtEt.append("n[" + format.format(new Date()) + "]" + msg.obj.toString()); break; case 1: tvMsg.setText("本机IP:" + GetIpAddress() + " 监听端口:" + msg.obj.toString()); break; case 2: Toast.makeText(getApplicationContext(), msg.obj.toString(), Toast.LENGTH_SHORT).show(); break; } } }; socketManager = new SocketManager(handler); } @Subscribe(threadMode = ThreadMode.MAIN) public void sendFileTcp(TcpEntity info) { long progress = info.getProgress(); send_progress.setText(bytes2kb(progress) + " /" + progress); } public static String bytes2kb(long bytes) { BigDecimal filesize = new BigDecimal(bytes); BigDecimal megabyte = new BigDecimal(1024 * 1024); float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP) .floatValue(); if (returnValue > 1) return (returnValue + "MB"); BigDecimal kilobyte = new BigDecimal(1024); returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP) .floatValue(); return (returnValue + "KB"); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == FILE_CODE && resultCode == Activity.RESULT_OK) { final String ipAddress = txtIP.getText().toString(); final int port = 9999; if (data.getBooleanExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, true)) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { ClipData clip = data.getClipData(); final ArrayList<String> fileNames = new ArrayList<>(); final ArrayList<String> paths = new ArrayList<>(); if (clip != null) { for (int i = 0; i < clip.getItemCount(); i++) { Uri uri = clip.getItemAt(i).getUri(); paths.add(uri.getPath()); fileNames.add(uri.getLastPathSegment()); } Message.obtain(handler, 0, "正在发送至" + ipAddress + ":" + port).sendToTarget(); Thread sendThread = new Thread(new Runnable() { @Override public void run() { socketManager.SendFile(fileNames, paths, ipAddress, port); } }); sendThread.start(); } } else { final ArrayList<String> paths = data.getStringArrayListExtra (FilePickerActivity.EXTRA_PATHS); final ArrayList<String> fileNames = new ArrayList<>(); if (paths != null) { for (String path : paths) { Uri uri = Uri.parse(path); paths.add(uri.getPath()); fileNames.add(uri.getLastPathSegment()); socketManager.SendFile(fileNames, paths, ipAddress, port); } Message.obtain(handler, 0, "正在发送至" + ipAddress + ":" + port).sendToTarget(); Thread sendThread = new Thread(new Runnable() { @Override public void run() { socketManager.SendFile(fileNames, paths, ipAddress, port); } }); sendThread.start(); } } } } } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } @SuppressLint("WifiManagerLeak") public String GetIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); int i = wifiInfo.getIpAddress(); return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + ((i >> 24) & 0xFF); } }
传送段的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/black" android:orientation="vertical" tools:context=".MainActivity"> <TextView android:id="@+id/tvMsg" android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="false" android:focusableInTouchMode="false" android:textColor="@color/white" /> <EditText android:id="@+id/txtIP" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:contentDescription="目标IP地址" android:ems="10" android:hint="请输入对方ip" android:textColor="@color/white" /> <EditText android:id="@+id/et" android:layout_width="match_parent" android:layout_height="180dp" android:layout_alignLeft="@+id/txtIP" android:clickable="false" android:editable="false" android:ems="10" android:focusable="false" android:focusableInTouchMode="false" android:gravity="center_vertical|left|top" android:inputType="textMultiLine" android:longClickable="false" android:scrollbarAlwaysDrawVerticalTrack="true" android:scrollbarStyle="insideInset" android:scrollbars="vertical" android:textColor="@color/white" android:textSize="15dp"> <requestFocus /> </EditText> <TextView android:id="@+id/send_progress" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="发送大小" android:textColor="@color/white" /> <Button android:id="@+id/btnSend" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignLeft="@+id/txtPort" android:layout_below="@+id/et" android:text="选择文件并发送" android:textColor="@color/white" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="@dimen/dimen_20" android:text="使用方法:n1:打开设备,退出到退出界面,n2:点击鼠标menu菜单按钮,点击5次,进入接受文件界面n3:双方设备须在同一wifi下n4:点击选择文件,后发送,n5:设备接受完毕,重启设备,等待升级" android:textColor="@color/white" /> </LinearLayout>
接收端的代码,里面有个二维码显示的功能,可以直接删除,我是准备用扫码传送的,
package com.mirror.activity; import android.annotation.SuppressLint; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.mirror.R; import com.mirror.config.AppInfo; import com.mirror.tcp.SendFileEntity; import com.mirror.tcp.SocketManager; import com.mirror.util.FileUtil; import com.mirror.util.ImageUtil; import com.mirror.util.QRCodeUtil; import com.mirror.view.MyToastView; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Date; public class TestTcpActiivty extends BaseActivity { private TextView tvMsg, tv_desc; private EditText txtEt; ImageView iv_bind_code; private SocketManager socketManager; private TextView tv_receiver_progress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EventBus.getDefault().register(this); setContentView(R.layout.activity_tcp); initView(); } private void initView() { tv_receiver_progress = (TextView) findViewById(R.id.tv_receiver_progress); iv_bind_code = (ImageView) findViewById(R.id.iv_bind_code); tv_desc = (TextView) findViewById(R.id.tv_desc); tvMsg = (TextView) findViewById(R.id.tvMsg); txtEt = (EditText) findViewById(R.id.et); socketManager = new SocketManager(handler); FileUtil.creatDirPathNoExists(); QRCodeUtil.createErCode(GetIpAddress(), AppInfo.BASE_QR_PATH + "/bindqu.jpg", 200, listener); } QRCodeUtil.ErCodeListener listener = new QRCodeUtil.ErCodeListener() { @Override public void createSuccess(String path) { Message message = new Message(); message.what = CREATE_IMAGE; message.obj = path; handler.sendMessage(message); } @Override public void createFailed(String error) { handler.sendEmptyMessage(CREATE_IMAGE_FAILED); } }; public static final int CREATE_IMAGE = 89; public static final int CREATE_IMAGE_FAILED = 90; Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case CREATE_IMAGE_FAILED: tv_desc.setText("图片创建失败,请手动输入IP地址,进行文件传输"); break; case CREATE_IMAGE: tv_desc.setText("扫描二维码,进行文件传输"); String path = (String) msg.obj; ImageUtil.loadImg(TestTcpActiivty.this, iv_bind_code, path); break; case 0: SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss"); txtEt.append("n[" + format.format(new Date()) + "]" + msg.obj.toString()); break; case 1: tvMsg.setText("本机IP:" + GetIpAddress() + " ( 监听端口:" + msg.obj.toString() + " )"); break; case 2: Toast.makeText(getApplicationContext(), msg.obj.toString(), Toast.LENGTH_SHORT).show(); break; } } }; @Subscribe(threadMode = ThreadMode.MAIN) public void sendFileTcp(SendFileEntity info) { long progress = info.getFileLength(); tv_receiver_progress.setText(progress + " k"); } public static String bytes2kb(long bytes) { BigDecimal filesize = new BigDecimal(bytes); BigDecimal megabyte = new BigDecimal(1024 * 1024); float returnValue = filesize.divide(megabyte, 2, BigDecimal.ROUND_UP) .floatValue(); if (returnValue > 1) return (returnValue + "MB"); BigDecimal kilobyte = new BigDecimal(1024); returnValue = filesize.divide(kilobyte, 2, BigDecimal.ROUND_UP) .floatValue(); return (returnValue + "KB"); } @SuppressLint("WifiManagerLeak") public String GetIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); int i = wifiInfo.getIpAddress(); return (i & 0xFF) + "." + ((i >> 8) & 0xFF) + "." + ((i >> 16) & 0xFF) + "." + ((i >> 24) & 0xFF); } @Override protected void onDestroy() { super.onDestroy(); EventBus.getDefault().unregister(this); } }
布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/tvMsg" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="TextView" android:textColor="@color/black" android:textSize="@dimen/text_25" /> <TextView android:id="@+id/tv_receiver_progress" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textColor="@color/gray" android:textSize="@dimen/text_20" /> <ImageView android:id="@+id/iv_bind_code" android:layout_width="@dimen/dimen_200" android:layout_height="@dimen/dimen_200" android:layout_gravity="center_horizontal" android:layout_marginTop="@dimen/dimen_30" /> <TextView android:id="@+id/tv_desc" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="扫描二维码进行文件传输" android:textColor="@color/gray" android:textSize="@dimen/text_20" /> <EditText android:id="@+id/et" android:layout_width="match_parent" android:layout_height="180dp" android:layout_marginTop="@dimen/dimen_15" android:editable="false" android:ems="10" android:focusable="false" android:focusableInTouchMode="false" android:gravity="center_vertical|left|top" android:inputType="textMultiLine" android:longClickable="false" android:scrollbarAlwaysDrawVerticalTrack="true" android:scrollbarStyle="insideInset" android:scrollbars="vertical" android:textSize="15dp"> <requestFocus /> </EditText> </LinearLayout>
最后
以上就是魁梧麦片为你收集整理的TCP 文件传输的全部内容,希望文章能够帮你解决TCP 文件传输所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复