有人可以告诉我我做错了什么吗?抱歉,这是一个漫长的问题,但是我已经阅读了很多文章并尝试了很多事情,甚至比下面描述的还要多。
我正在尝试使用BluetoothChat示例作为基础通过Bluetooth传输文件,而超过1024k的任何内容我都无法成功传输。我的目标是使应用程序定期传输文件(每分钟1个文件),而无需用户交互(一旦用户启动了文件),因此需要透明地进行传输;因此希望通过代码而不是使用意图来实现。
1)基础。在BluetoothFragment中,我有
private void transferFile(String file) {
File imageFile = new File(getActivity().getExternalFilesDir(null), file);
if (!imageFile.exists()) {
...; return;
} else {
try {
byte[] myByteArray = new byte[(int)imageFile.length()];
FileInputStream fis = new FileInputStream(imageFile);
BufferedInputStream bis = new BufferedInputStream(fis);
bis.read(myByteArray,0,myByteArray.length);
mBluetoothService.transferOut(myByteArray);
} catch (IOException e) {
e.printStackTrace();
和在BluetoothService中
public void transferOut(byte[] out) {
ConnectedThread r;
synchronized (this) {
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
r.transferOut(out);
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
...
public void transferOut(byte[] buffer) {
try {
//tried this
// mmOutStream.write(buffer);
//then this
// for(int i = 0 ; i < buffer.length ; i++) {
// mmOutStream.write(buffer[i]);}
//then this. All had same results.
mmOutStream.write(buffer, 0, buffer.length);
...
public void run() {
byte[] buffer = new byte[1024];
int bytes, current;
while (mState == STATE_CONNECTED) {
try {
bytes = mmInStream.read(buffer);
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
如果文件为<1024k,则BluetoothFragment中的处理程序会将其正确写入磁盘;如果较大,则会被裁剪。
2)找到此建议以重复阅读。将ConnectedThread run()更改为
try {
bytes = mmInStream.read(buffer, 0, buffer.length);
current = bytes;
do {
bytes = mmInStream.read(buffer, current, buffer.length - current);
if (bytes >= 0)
current += bytes;
} while (bytes > -1);
mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
但是它停留在do循环中,大概没有得到闭合的连接字节-1)。
3)另一个版本
public void run() {
byte[] imgBuffer = new byte[2048 * 2048];
int pos = 0;
while (mState == STATE_CONNECTED) {
try {
byte[] buffer = new byte[2048];
int bytes = mmInStream.read(buffer);
System.arraycopy(buffer, 0, imgBuffer, pos, bytes);
pos += bytes;
mHandler.obtainMessage(Constants.MESSAGE_READ, pos, -1, imgBuffer)
.sendToTarget();
这有时可能有效,但即使如此也要花费很长时间(也许20分钟,只有几MB-有时最终结果是前一张图像!即使在测试中,我还是手动将其删除!)。
4)正在发送文件大小。要测试该概念,请从2个步骤开始。首先发送文件大小:
File imageFile = new File(getActivity().getExternalFilesDir(null), file);
String inputString = FILE_LENGTH + (int)imageFile.length();
byte[] myByteArrayLgth = new byte[1024];
myByteArrayLgth = inputString.getBytes();
mService.transferOutFileLength(myByteArrayLgth);
然后在ConnectedThread run()中手动说明文件大小,以最大程度地减少错误。尝试了几种方法,最后一种是:
public void run() {
byte[] buffer = new byte[80 * 1024];
int bytes, current;
int targetFileSize = 57828;
while (mState == STATE_CONNECTED) {
try {
bytes = mmInStream.read(buffer);
current = bytes;
while (current < targetFileSize) {
bytes = mmInStream.read(buffer);
current = current + bytes;
}
mHandler.obtainMessage(Constants.MESSAGE_READ, current, -1, buffer)
.sendToTarget();
还将写入磁盘的内容更改为
fos.write(readBuf, 0, arg1); //arg1 is filesize
此生成的文件的类型(jpeg)和大小正确,但无法显示(可能已损坏)。
有人能看到做错了什么或提出更好的方法吗? 也许蓝牙消息/块的大小和顺序太不可预测了;也许我应该考虑使用Wifi? 我正在测试的2个设备是Android 8.0.0和4.4.3。 (因此为sdk 19)。