利用android 传送文件需要解决一下几个问题。
1,发送方选中文件时如何获取文件地址?
以下这段代码作用是返回你选择文件的uri,因此你要重写
onActivityResult来获取返回的uri。但是这里有有两种情况存在先看下图。
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("*/*");
startActivityForResult(intent, 1);
当你选择图库的时候选择其中一张图片返回的uri为:content://media/external/images/media/530405 后面的数字是图片存储在图库数据库中的_id,
当你选择文件管理的时候选择其中的一个文件返回的uri为: file:///storage/emulated/0/tencent/QQfile_recv/%E9%A2%98%E7%9B%AE.txt
因此要获取文件的地址需要分两种情况进行获取。
情况一:你可以利用
ContentResolver这个类根据图片的_id获取图片存储在数据库中地址。
一下代码可以获取在图库中图片地址
String path=null;
ContentResolver resolver = this.getContentResolver();
//uri.getLastPathSegment()这个是获取content://media/external/images/media/530405后面的数字也就是_id
path = getFilePath(resolver, uri, uri.getLastPathSegment());
//
private String getFilePath(ContentResolver resolver,Uri uri,String _id) {
String _data=null;
Cursor cursor = resolver.query(uri, null,"_id="+_id, null, null);
while (cursor.moveToNext()) {
_data = cursor.getString(cursor.getColumnIndex("_data"));//表示文件的存储路径
String displayName = cursor.getString(cursor.getColumnIndex("_display_name"));//表示文件名
String mimeType = cursor.getString(cursor.getColumnIndex("mime_type"));//媒体类型:image/jpeg之类的
Log.d("test", "_data:" + _data + ",displayName:" + displayName + ",mimeType:" + mimeType);
}
return _data;
}
情况二:这个uri你可以利用path=uri.getPath();这个方法获取uri的路径以下是我获取选中文件的路径
/storage/emulated/0/tencent/QQfile_recv/题目.txt
2,接受方如何获取发送方的文件名及文件类型?
这里我是发送方文件名和路径前后放一个标识然后将其写入流中,接受方然后解析出文件类型及文件名,
//发送及读取文件,这里发送文件要放在子线程中不然传送大文件时会导致主线程阻塞
class ReceiveFile extends Thread {
private BluetoothSocket socket;
private InputStream inputStream;
private File receiveFile;
private String filePath;
private String name;
private String content;
private volatile FileOutputStream outputStream=null;
public ReceiveFile(BluetoothSocket socket) {
this.socket = socket;
filePath = Environment.getExternalStorageDirectory().getPath();
File file = new File(filePath, "you");
if (!file.exists()) {
file.mkdir();
}
filePath = file.getPath();
}
@Override
public void run() {
try {
inputStream = socket.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
while (true) {
try {
handler.sendEmptyMessage(3);
byte[] buff = new byte[1024];
int length = 0;
//当没有数据时会阻塞,却并不会返回-1,
// 并且这里不建议使用,while((length=inputStream.read(buff,0,buff.length))!-1)这种写法
length = inputStream.read(buff);
//文件名包含在第一个数据块中
content = new String(buff, 0, length);
/*Log.d("test", "content--->:" + content);*/
Log.d("test", "begin:" + content.startsWith("begin"));
if (content.startsWith("begin")) {
//保证再次传送数据时数据不会写入第一个文件中,这句很重要
outputStream=null;
if (outputStream == null) {
Log.d("test", "outputStream ===null");
}else {
Log.d("test", "outputStream !=null");
}
flag++;
name = getFileName(content);
Log.d("test", "flag:" + flag+",name:"+name);
/*outputStream=null*/;//解决
}
outputStream = getOutputStream(filePath, name);
if (content.startsWith("begin")) {
outputStream.write(getBytes(content));
continue;
}
outputStream.write(buff, 0, length);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//一个传送只得到一个FileOutputStream
private synchronized FileOutputStream getOutputStream(String path, String name) {
Log.d("test", "getOutput");
if (outputStream == null) {
try {
receiveFile=new File(path, name);
if (!receiveFile.exists()) {
receiveFile.createNewFile();
}
outputStream = new FileOutputStream(receiveFile);
Log.d("test", "receiveFile:" + receiveFile.getName());
} catch (Exception e) {
e.printStackTrace();
}
}else {
Log.d("test", "getOutPutStream outputStream !=null");
}
return outputStream;
}
//返回解析传来的真实数据
private synchronized byte[] getBytes(String content) {
int end = content.lastIndexOf("end");
byte[] bytes = content.substring(end + 3).getBytes();
return bytes;
}
//根据传送过来的数据解析出文件名
private synchronized String getFileName(String content) {
int begin = content.indexOf("begin");
int end = content.lastIndexOf("end");
String name = content.substring(begin + 5, end);
return name;
}
//先将标识,文件及文件名写入流中,然后将文件数据写入流中
public void SendFile(File file) {
try {
Log.d("test", file.getPath() + ":" + file.getName());
String name = "begin" + file.getName() + "end";
FileInputStream inputStream = new FileInputStream(file);
OutputStream outputStream = socket.getOutputStream();
byte[] buff = new byte[1024];
int length = 0;
//第一次写入的是名字
outputStream.write(name.getBytes());
//第二次写入的是数据
while ((length = inputStream.read(buff, 0, buff.length)) != -1) {
outputStream.write(buff, 0, length);
}
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}