我的目的是通过蓝牙socket发送一张图片,我是把图片转成byte[]类型发送的。接收端单步执行就可以收完图片,直接运行就接收不完了,困惑啊!
发送端代码:
OutputStream mOutStream = msocket.getOutputStream();
// 向socket对象所获取的流中发送数据
try {
Resources res=getResources();
Bitmap bitmap=BitmapFactory.decodeResource(res, user.imageId);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG,100,bos);
byte[] photo = bos.toByteArray();
mOutStream.write(photo);
mOutStream.flush();
} catch (IOException e) {e.printStackTrace(); }
接收端代码: if (socket != null) {
//从socket流中读取数据
try {
mmInStream = socket.getInputStream();
byte[] buffer = new byte[4096];
int temp = 0;
String str1 = "icon.png";
OutputStream os=receivecard.this.openFileOutput(str1,MODE_WORLD_READABLE);
while( (temp = mmInStream.read(buffer)) != -1) {
os.write(buffer, 0, temp);
}
System.out.println("传输结束"); //接收完后跳到名字叫ShowPicture的这个activity
Intent intent = new Intent(receivecard.this, ShowPicture.class);
startActivity(intent);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
//此方法关闭socket
cancel();
}
} 现在的问题是,执行这一段代码时,不会自动结束。举个例子:假设我的图片有13523byte这么长,然后我每次接收4096byte,因为 13523 = 4096*3 + 1235 ,所以,在循环前三次时,temp的值均为4096,而在循环到第四次时,temp的值为1235,将这1235字节读完后,再去while中判断temp是否为-1.理论上说此时temp应该变为-1然后循环退出,但实际上此时temp一直是1235,循环退不出去,程序就死到这里了。不知道为啥??while( (temp = mmInStream.read(buffer)) != -1) {
os.write(buffer, 0, temp);
}以上是第一个问题。为了解决这个问题,我把代码改成了这样:
while( (temp = mmInStream.read(buffer)) != -1) {
os.write(buffer, 0, temp);
if(temp != 4096) break;
}
System.out.println("传输结束"); //接收完后跳到名字叫ShowPicture的这个activity
Intent intent = new Intent(receivecard.this, ShowPicture.class);
startActivity(intent);
加了一个if语句判断,这样最后一次即使temp没有变为-1,它也能跳出来,嘿嘿但是新问题又来了!!!!!经实际测试发现,这段代码,根本不能接收完全我的图片,可以说,大概只接受了图片的一个角,就打印出了传输结束,并开始执行下面的intent代码,跳转到下一个activity了!!于是我很困惑地单步执行,居然成功了!只有单步执行的时候才能接收完数据,直接全部执行的时候,只能收到图片的一个角,就跳到下面的代码了!这可怎么办??求高人指点迷津!小生感激不尽啊!~
发送端代码:
OutputStream mOutStream = msocket.getOutputStream();
// 向socket对象所获取的流中发送数据
try {
Resources res=getResources();
Bitmap bitmap=BitmapFactory.decodeResource(res, user.imageId);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG,100,bos);
byte[] photo = bos.toByteArray();
mOutStream.write(photo);
mOutStream.flush();
} catch (IOException e) {e.printStackTrace(); }
接收端代码: if (socket != null) {
//从socket流中读取数据
try {
mmInStream = socket.getInputStream();
byte[] buffer = new byte[4096];
int temp = 0;
String str1 = "icon.png";
OutputStream os=receivecard.this.openFileOutput(str1,MODE_WORLD_READABLE);
while( (temp = mmInStream.read(buffer)) != -1) {
os.write(buffer, 0, temp);
}
System.out.println("传输结束"); //接收完后跳到名字叫ShowPicture的这个activity
Intent intent = new Intent(receivecard.this, ShowPicture.class);
startActivity(intent);
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
//此方法关闭socket
cancel();
}
} 现在的问题是,执行这一段代码时,不会自动结束。举个例子:假设我的图片有13523byte这么长,然后我每次接收4096byte,因为 13523 = 4096*3 + 1235 ,所以,在循环前三次时,temp的值均为4096,而在循环到第四次时,temp的值为1235,将这1235字节读完后,再去while中判断temp是否为-1.理论上说此时temp应该变为-1然后循环退出,但实际上此时temp一直是1235,循环退不出去,程序就死到这里了。不知道为啥??while( (temp = mmInStream.read(buffer)) != -1) {
os.write(buffer, 0, temp);
}以上是第一个问题。为了解决这个问题,我把代码改成了这样:
while( (temp = mmInStream.read(buffer)) != -1) {
os.write(buffer, 0, temp);
if(temp != 4096) break;
}
System.out.println("传输结束"); //接收完后跳到名字叫ShowPicture的这个activity
Intent intent = new Intent(receivecard.this, ShowPicture.class);
startActivity(intent);
加了一个if语句判断,这样最后一次即使temp没有变为-1,它也能跳出来,嘿嘿但是新问题又来了!!!!!经实际测试发现,这段代码,根本不能接收完全我的图片,可以说,大概只接受了图片的一个角,就打印出了传输结束,并开始执行下面的intent代码,跳转到下一个activity了!!于是我很困惑地单步执行,居然成功了!只有单步执行的时候才能接收完数据,直接全部执行的时候,只能收到图片的一个角,就跳到下面的代码了!这可怎么办??求高人指点迷津!小生感激不尽啊!~
os.write(buffer, 0, temp);
}
第一个问题,因为read是阻塞的,stream中 没有数据时,不是返回-1,而是阻塞在那儿,所以退不出来。while( (temp = mmInStream.read(buffer)) != -1) {
os.write(buffer, 0, temp);
if(temp != 4096) break;
}
第二个问题,虽然你一次write的是4096个字节,但是另外一端可能是分几次才把4096个read结束,所以就会出现文件没有传输完,循环就退出了。
确保一次可以读到4096个数据的正确做法是这样:
temp = mmInStream.read(buffer);
while (temp < 4096){
temp += mmInStream.read(buffer, temp, 4096-temp);
}
这样做虽然确保一次读完4096个字节,问题是最后一个包肯定小于4096个字节,程序依旧会阻塞。
给两个建议:
1. 传文件之前,將文件大小先传过去,这样接收端可以根据收到的包的字节数判断是否已经接受完整
2. 设置包头,比如每个包的第一个字节表示该包为文件片段或者文件结尾。可以假设0x00开头的包为文件片段,0xEE开头的包爲文件结尾,然后从第二个字节开始为文件数据。