Corrupt audio file after copying over bluetooth stream - android

I am sending a audio file by sending it over a bluetooth socket connection to another device. I am copying byte for byte, so the size on the other end is exactly the same.
However, when I try to play the file on the other end, I just get awkward noises (each time i start the player it sounds a little different).
Now the strange part: As soon as I copy the "corrupt" file to another location (via some android file manager), I can play it and it sounds totally fine!
Any ideas?
sending:
outputStream = mSocket.getOutputStream();
long totalLength = file.length();
String command = Protocol.COMMAND_SEND_FILE + Protocol.SEPARATOR + file.getName() + Protocol.SEPARATOR + totalLength;
outputStream.write(command.getBytes());
outputStream.flush();
long bytesWritten = 0;
while ((c = is.read(buffer, 0, buffer.length)) > 0) {
outputStream.write(buffer, 0, c);
outputStream.flush();
bytesWritten += c;
}
mLogger.log("sent total of bytes", bytesWritten+"");
is.close();
receiving:
while (mRunning) {
final StringBuilder sb = new StringBuilder();
if (!mReceiveFile) {
bytesRead = mInputStream.read(buffer);
if (bytesRead != -1) {
String result = "";
while ((bytesRead == bufferSize) && (buffer[bufferSize] != 0)) {
result = result + new String(buffer, 0, bytesRead);
bytesRead = mInputStream.read(buffer);
}
result = result + new String(buffer, 0, bytesRead);
sb.append(result);
}
} else {
if (mLogger != null) {
mLogger.log("receiving file", mReceiveFilename);
}
int c = 0;
long bRead = 0;
OutputStream oos = new FileOutputStream(Utils.getAppRootDir() + "/" + mReceiveFilename);
while (bRead < mReceiveFileLength && (c = mInputStream.read(buffer, 0, buffer.length)) > 0) {
if ((bRead + bufferSize) >= mReceiveFileLength) {
c = (int) (mReceiveFileLength - bRead);
mLogger.log("rest bytes", "" + c);
}
if(bRead < 10000 || bRead + 10000 > mReceiveFileLength){
mLogger.log(new String(buffer));
}
oos.write(buffer, 0, c);
oos.flush();
bRead += c;
mLogger.log("read " + bRead + " of " + mReceiveFileLength + " bytes");
}
oos.close();
mLogger.log("saved file", mReceiveFilename);
mReceiveFile = false;
mReceiveFilename = null;
}
if (sb.toString().startsWith(Protocol.COMMAND_SEND_FILE)) {
// "SEND_FILE:filename.ext"
try {
String[] command = sb.toString().split(Protocol.SEPARATOR);
mReceiveFile = true;
mReceiveFilename = command[1];
mReceiveFileLength = Long.parseLong(command[2]);
} catch (Exception e) {
mLogger.log("Protocoll exception command could not be parsed:" + sb.toString());
}
} else {
EventBus.getDefault().post(new BluetoothCommunicator(sb.toString()));
}
}

I figured out that I have to start the media scanner after creating the new file. After that it plays like a charm!
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));

Related

Writing to the file system is taking too long

I am trying to download around 300-400 image files using the optimal number of threads(around 20-30) and then writing these images into the file system of Android. The problem is that the whole process is taking 10-13 minutes and I want to clock it around 2-3 minutes with high-speed internet
I think this can be achieved as the size of those 300-400 image files is in some KBs only(total size would be around 80-100 MB)
Here's my code for downloading and saving file
long t1 = System.currentTimeMillis();
Call<ResponseBody> call=apiService.fetchAttachmentDetail(att_id,token,true,device_id, 0.0f, 0.0f);
Response<ResponseBody> response = call.execute();
long t2 = System.currentTimeMillis();
Help.E("downloaded " + att_id + "and time taken in mili second " + (t2 - t1));
Help.E("content length- " + response.body().contentLength());
String str = response.headers().get("Content-Type");
if (str == null)
str = "/png";
String ext_type = str.substring(str.indexOf("/") + 1);
InputStream in = null;
FileOutputStream out = null;
ContextWrapper cw = new ContextWrapper(context);
String fileName = "";
File directory = cw.getDir(AttachmentDirName, Context.MODE_PRIVATE);
try {
in = response.body().byteStream();
fileName = String.valueOf(att_id) + "." + ext_type;
File file = new File(directory, fileName);
out = new FileOutputStream(file);
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
} catch (IOException e) {
Log.d("Error", e.toString());
emitter.onError(e);
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
long t3 = System.currentTimeMillis();
Help.E("saved " + att_id + "time taken in saving the file " + (t3 - t2));
You are reading and writing your data byte by byte, it takes significantly more time compared with reading and writing with a buffer. Try to use this method:
public static void copyStream(InputStream input, OutputStream output)
throws IOException
{
byte[] buffer = new byte[1024]; // Adjust if you want
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
}
So you replace your
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
with
copyStream(in, out);

Recieving File with Socket in Android

I want to transfer a file between server and client, Server is a Windows program written in Delphi with Indy and Client is an Android
this is my client code for reading from socket :
...
InputStream IS = S.getInputStream();
byte[] FBytes = new byte[FileSize];
FileOutputStream FOS = new FileOutputStream(TempFile);
BufferedOutputStream BOS = new BufferedOutputStream(FOS);
int BytesRead = IS.read(FBytes);
int CurrProgress = BytesRead;
do {
Log.d("DOWNLOAD", "BytesRead2 = " + Integer.toString(BytesRead));
if(CurrProgress < FBytes.length) {
Log.d("DOWNLOAD", "prog < BytesRead" );
BytesRead = IS.read(FBytes);
if (BytesRead > 0)
CurrProgress += BytesRead;
B.clear();
B.putInt("ProgValue", CurrProgress);
Msg.what = MSG_FILE_PROGRESS;
Hdlr.dispatchMessage(Msg);
Log.d("DOWNLOAD", "BytesRead = " + Integer.toString(BytesRead));
}
} while (BytesRead > 0);
Log.d(TAG, "Download Loop Finished");
File will download but the problem is size of downloaded file is lower than original file and the socket read command stay on last read. in other words file has been downloaded but CurrProgress is lower than FBytes.length so while loop execute onetime more and program hangs on read command because there is no more data sent from server
I have been tested server with an windows program and there is no problem in the server code
I have tested many ways like this but no chance :
int BytesRead = IS.read(FBytes, 0, FBytes.length);
int CurrProgress = BytesRead;
do {
Log.d("DOWNLOAD", "BytesRead2 = " + Integer.toString(BytesRead));
if(CurrProgress < FBytes.length) {
Log.d("DOWNLOAD", "prog < BytesRead" );
BytesRead = IS.read(FBytes, CurrProgress, (FBytes.length - CurrProgress));
...
FileSize value is correct and came from server as a string value before reading file bytes
What goes wrong ?!, thanks ...
Edit :
Complete code do many other jobs but code of reading file is like this :
public void Run()
{
Running = true;
try{
try{
InetAddress ServerAddr = InetAddress.getByName(SERVER_IP);
S = new Socket(ServerAddr, SERVER_PORT);
Log.d(TAG, "Connecting ...");
Out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(S.getOutputStream())), true);
In = new BufferedReader(new InputStreamReader(S.getInputStream()));
switch (Job) {
...
}
case GetFile: {
this.SendMessage(Cmd);
response = In.readLine();
if(response.equals("1"))
{
Hdlr.sendEmptyMessage(MSG_SERVER_ACCEPT);
response = In.readLine();
int FileSize = Integer.parseInt(response);
if (context.getFilesDir().getFreeSpace() < 3 * FileSize)
{
Hdlr.sendEmptyMessage(MSG_ERROR_FREESPACE);
Log.d(TAG, "There is no Free Space !");
}
else {
final Message Msg = new Message();
final Bundle B = new Bundle();
B.putInt("FSize", FileSize);
Msg.what = MSG_FILE_SIZE;
Msg.setData(B);
Hdlr.dispatchMessage(Msg);
try {
File TempDir, TempFile, MainDir, MainFile;
switch(FileType)
{
case 2 :
TempDir = new File(context.getCacheDir(), "TempMP3");
if(!TempDir.exists()) {
TempDir.mkdir();
}
TempFile = new File(TempDir, Integer.toString(FileIndex) + ".mp3");
if(TempFile.exists()) {
TempFile.delete();
}
break;
default :
TempDir = new File(context.getCacheDir(), "TempLevel");
if(!TempDir.exists()) {
TempDir.mkdir();
}
TempFile = new File(TempDir, Integer.toString(FileIndex) + ".zip");
if(TempFile.exists()) {
TempFile.delete();
}
}
InputStream IS = S.getInputStream();
byte[] FBytes = new byte[4096];
FileOutputStream FOS = new FileOutputStream(TempFile);
BufferedOutputStream BOS = new BufferedOutputStream(FOS);
int BytesRead = 0;
int CurrProgress = 0;
do {
Log.d("DOWNLOAD", "prog < BytesRead" );
BytesRead = IS.read(FBytes, 0, FBytes.length);
BOS.write(FBytes, 0, BytesRead);
if (BytesRead > 0)
CurrProgress += BytesRead;
B.clear();
B.putInt("ProgValue", CurrProgress);
Msg.what = MSG_FILE_PROGRESS;
Hdlr.dispatchMessage(Msg);
Log.d("DOWNLOAD", "BytesRead = " + Integer.toString(BytesRead));
} while (CurrProgress < FileSize);
Log.d(TAG, "Download Loop Finished");
if (CurrProgress != FBytes.length) {
BOS.close();
Hdlr.sendEmptyMessage(MSG_ERROR_FILESIZE);
Log.d(TAG, "File Size Problem");
} else {
BOS.close();
Log.d(TAG, "File Downloaded successfully, Preparing to Unzip ... ");
try {
MainDir = new File(context.getFilesDir(), "Levels");
if(!MainDir.exists())
{
MainDir.mkdir();
}
File LevelDir = new File(MainDir, Integer.toString(FileIndex));
if(!LevelDir.exists())
{
LevelDir.mkdir();
}
else
{
LevelDir.delete();
}
FileInputStream fin = new FileInputStream(TempFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
MainFile = new File(LevelDir, ze.getName());
FileOutputStream FOut = new FileOutputStream(MainFile);
for (int c = zin.read(); c != -1; c = zin.read()) {
FOut.write(c);
}
zin.closeEntry();
FOut.close();
}
zin.close();
} catch (Exception e) {
Log.d(TAG, "Unzip Error : ", e);
}
}
} catch (Exception E) {
Err = 1;
Log.d(TAG, "Get File Error : ", E);
}
}
}
else
{
if (Listener != null)
{
Listener.callbackMessageReceiver(response);
Hdlr.sendEmptyMessage(MSG_ERROR_SERVER);
}
}
break;
}
...
}
}catch (Exception e)
{
Hdlr.sendEmptyMessage(MSG_ERROR_SEND);
Log.d(TAG, "Connect Error : ", e);
}
finally{
if(Out != null) {
Out.flush();
Out.close();
}
if(In != null)
{
In.close();
}
S.close();
Log.d(TAG, "Err Value is : " + Integer.toString(Err));
if(Err == 0)
{
Hdlr.sendEmptyMessage(MSG_SUCCESS);
}
Log.d(TAG, "Sending Ends");
}
}catch (Exception E){
Log.d(TAG, "Error : ", E);
}
}
CurrProgress is lower than FileSize ( the difference is about 4 or 5 KB ) and the while loop hangs on read command !
Problem solved, I will post it as answer, it may be useful
The problem was that server sends File immediately after sending FileSize and I think the BufferedReader gets some bytes of File so the size of bytes given by IS are lower than FileSize, example of Server :
...
WriteLn(FileSize);
Write(FileStream);
...
Now, Server first sends FileSize then wait for a response from client, after checking freespace in client it sends a Ready response to server and then Server sends the File Stream, for example :
...
WriteLn(FileSize);
Response := ReadLn();
if Response = "READY" then
Write(FileStream);
...
and codes in client are like this :
...
BufferedInputStream BIS = new BufferedInputStream(S.getInputStream());
In = new BufferedReader(new InputStreamReader(S.getInputStream()));
...
response = In.readLine();
int FileSize = Integer.parseInt(response);
if (context.getFilesDir().getFreeSpace() < 3 * FileSize)
{
Hdlr.sendEmptyMessage(MSG_ERROR_FREESPACE);
Log.d(TAG, "There is no Free Space !");
this.SendMessage("NOT_READY");
}
else {
...
try {
this.SendMessage("READY");
byte[] FBytes = new byte[8192];
FileOutputStream FOS = new FileOutputStream(TempFile);
BufferedOutputStream BOS = new BufferedOutputStream(FOS);
int BytesRead = 0;
int CurrProgress = 0;
while (CurrProgress < FileSize){
Log.d("DOWNLOAD", "Available : " + Integer.toString(BIS.availabl
BytesRead = BIS.read(FBytes, 0, FBytes.length);
BOS.write(FBytes, 0, BytesRead);
if (BytesRead > 0)
CurrProgress += BytesRead;
B.clear();
B.putInt("ProgValue", CurrProgress);
Msg.what = MSG_FILE_PROGRESS;
Hdlr.dispatchMessage(Msg);
Log.d("DOWNLOAD", "BytesRead = " + Integer.toString(BytesRead));
}
There is no problem and everything works fine

Is it possible to play a partial mp3 audio file as bytes gets copied in Input Stream

Two devices are connected using bluetooth. Is it possible to play a mp3 song as it is being received .
while (fileSize >= TConstants.CHUNK_SIZE)
{
int readLen = 0;
readLen = inputStream.read(buf, 0, TConstants.CHUNK_SIZE);
if (readLen < 0)
throw new TException(TException.EXCEPTION_READ_FILE);
out.write(buf, 0, readLen);
len += readLen;
fileSize -= readLen;
if (listener!=null && ((len / TConstants.CHUNK_SIZE) != prev))
{
prev = len / TConstants.CHUNK_SIZE;
Log.d(TAG, "Chunk read " + prev + "");
receiverConsignment.setReadFileSize(len);
listener.onChunkRead(receiverConsignment);
// showSpinnerProgress(fileTransferModel);
}
}
while (fileSize > 0)
{
buf = new byte[(int) fileSize];
len = inputStream.read(buf);
if (len < 0)
{
throw new TException(TException.EXCEPTION_READ_FILE);
}
fileSize -= len;
out.write(buf, 0, len);
}
out.close();
}
catch (IOException e)
{
Log.e(TAG, "Exception in copyFile: ", e);
out.close();
throw new TException(e, TException.EXCEPTION_READ_FILE);
}

Bluetooth file transfer hangs when I send large files

I've implemented bluetouth file transfer according to the example: http://developer.android.com/guide/topics/connectivity/bluetooth.html
I've faced with an issue: when I do transfer of a large (50-100Mb) file in the most cases the
transfer process is stuck at any point of the transfer process. Log info says that process stops at the point of write(sender) and read(receiver).When stuck - the total bytes number recorded by sender to a stream is always exceeds the amount of bytes have been read by receiver.The subtraction: received - sent data is equal to 4-7 Kb.
It seems that in certain moment the read method can't do actual READ.
Sometimes 100Mb trasfer passes successfully.
Could you please help me with that?
Thanks in advance
Receiver :
try {
BufferedInputStream bis = new BufferedInputStream(mSocket.getInputStream());
File file = new File(root, progressData.file.getFileName());
FileOutputStream fileStream = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fileStream);
DialogsCaller dialog = DialogsCaller.getInstance();
long bytesRead = 0;
int len = 0;
long size = progressData.file.getFileSize();
int bufSize = Constants.BUFFER_SIZE * 8;
byte[] buffer = new byte[bufSize];
int timeOut = 0;
int maxTimeOut = 16;
while (bytesRead < size) {
Log.w(TAG, "BEFORE AVAILABLE " + bytesRead);
while (bis.available() == 0 && timeOut < maxTimeOut) {
timeOut++;
Thread.sleep(250);
}
long remainingSize = size - bytesRead;
int byteCount = (int) Math.min(remainingSize, bufSize);
Log.w(TAG, "BEFORE READ " + "currentSize : "
+ bytesRead + " byteCount " + byteCount);
len = bis.read(buffer, 0, byteCount);
Log.w(TAG, "AFTER READ " + "Len " + len);
if (len > 0) {
timeOut = 0;
Log.w(TAG, "BEFORE WRITE " + bytesRead);
bos.write(buffer, 0, len);
bytesRead += len;
Log.w(TAG, "AFTER WRITE " + bytesRead);
dialog.setProgress(
progressData, (int) bytesRead);
}
}
bos.flush();
} catch (Exception e) {
Callback.post(e);
Log.e(TAG, "Receiving problem");
mHandler.obtainMessage(MessageType.CANNOT_RECEIVE_DATA)
.sendToTarget();
throw e;
} finally {
if (bos != null) {
try {
Log.i(TAG, "FILE CLOSE");
bos.close();
} catch (IOException e) {
Callback.post(e);
}
}
}
Sender :
try {
File file = new File(progressData.file.getFilePath());
FileInputStream fileStream = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fileStream);
BufferedOutputStream bos = new BufferedOutputStream(
mCurrentSocket.getOutputStream());
long sentBytes = 0;
int len = 0;
byte[] buffer = new byte[Constants.BUFFER_SIZE];
DialogsCaller dialog = DialogsCaller.getInstance();
while ((len = bis.read(buffer)) > -1) {
if (len > 0) {
Log.w("F_" + TAG, "BEFORE " + "currentSize : " + sentBytes
+ "Len " + len);
bos.write(buffer, 0, len);
bos.flush();
sentBytes += len;
Log.w("F_" + TAG, "AFTER " + "currentSize : " + sentBytes);
dialog.setProgress(progressData, (int) sentBytes);
// SystemClock.sleep(120);
}
}
} catch (Exception e2) {
Callback.post(e2);
Log.e(TAG, "Sending problem");
mHandler.obtainMessage(MessageType.CANNOT_SEND_DATA).sendToTarget();
throw e2;
} finally {
try {
if (bis != null) {
bis.close();
}
} catch (IOException e) {
Callback.post(e);
Log.e(TAG, "Stream not closed");
}
}
You can throttle while you are sending data...few milliseconds delay before you send the next chunk of data..Also reduce the buffer size based on the target device..I had faced similar issue.After tuning the buffer size based on target device it works..You will have to implement some logic to get the target device.
The blutooth communication in android is flaky(because of different radios and implementation) you will have to try different things before it starts working properly on all the devices.

android app connecting to google drive and downloading a file to sd card

My android app connects to google drive and checks for a file on the drive, if the file isn't present then it downloads it to sdcard. the following code does the downloading .
the problem that occurs is that the file which gets downloaded is showing 0 bytes after downloading. please help me locate the error in the code. thanks for helping out .
private void savefile(String filename, InputStream in , Boolean replace ) {
try {
java.io.File f = new java.io.File(filename);
logonscreen("trying to savefile :"+filename);
if(replace) {
showToast("replace:"+replace.toString());
OutputStream stream = new BufferedOutputStream(new FileOutputStream(filename));
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = in.read(buffer)) != -1) {
stream.write(buffer, 0, len);
}
if(stream!=null) {
stream.close();
}
} else {
showToast("replace: "+replace.toString()+" , file exists " + f.exists());
if(f.exists()== false) {
OutputStream stream = new BufferedOutputStream(new FileOutputStream(filename));
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = in.read(buffer)) != -1) {
stream.write(buffer, 0, len);
}
if(stream!=null) {
stream.close();
}
}
}
//Do something
} catch (IOException e) {
// TODO: handle exception
logonscreen("exception at Save File:" +filename + "exception" + e.getMessage());
// showToast("exception:" + e.getMessage());
} catch (Exception e) {
logonscreen("exception at Save File:" + e.getMessage());
// showToast("exception:" + e.getMessage());
e.printStackTrace();
}
}

Categories

Resources