I am using Cronet API with our current API stack, specifically UploadDataProvider, there is a ByteBuffer with preset limit, seems like the limit size is fixed and we need to pass the data chunk by chunk. Our current API uses InputStream, and write chunk to OutputStream. We're using following code to work with infinite size of file:
byte[] buf = new byte[16 * 1024];
int bytesRead;
while ((bytesRead =inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
I'd like to achieve the same for this Cronet API, UploadDataProvider. My plan was in its read(UploadDataSink, ByteBuffer) method, whenever this read() method was called, read ByteBuffer's limit from inputStream, but my following code not working as expected.
public class MyUploadDataProvider extends UploadDataProvider {
private ReadableByteChannel byteChannel;
MyUploadDataProvider(InputStream inputStream) {
byteChannel = Channels.newChannel(inputStream);
}
#Override
public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) throws IOException {
boolean finalChunk = false;
int read = this.byteChannel.read(byteBuffer);
if (read == -1) {
finalChunk = true;
}
uploadDataSink.onReadSucceeded(finalChunk);
}
}
Not sure why it read failed, can anyone please help me fix this? Thanks!
Related
My interface:
public interface Downloader {
#Streaming #GET Call<ResponseBody> get(#Url final String url);
}
My download method:
private void download(final String url, final File zip) throws IOException {
AsyncHelper.assertNotMainThread();
final Call<ResponseBody> call = downloaderInstance.get(url);
final Response<ResponseBody> response = call.execute();
if (!response.isSuccessful()) {
downloadFailed(response.code());
return;
}
final ResponseBody body = response.body();
downloadedBytes = 0;
totalBytes = body.contentLength();
final InputStream in;
final OutputStream fout;
in = body().byteStream();
fout = new FileOutputStream(zip);
int read;
while ((read = in.read(BUFFER)) != -1) {
fout.write(BUFFER, 0, read);
downloadedBytes += read;
LOG.d("wrote %d bytes (total: %d)", downloadedBytes, totalBytes);
}
body.close();
fout.close();
}
This whole thing runs on a background thread and I don't get any log lines with "wrote x bytes (total: y)" in the log, which tells me that it's not streaming.
In a previous implementation I was running this stream directly into a ZipInputStream to unzip on the fly, I split the process into download and decompress steps thinking that the ZipInputStream might be the problem. The process fails during download, which means once I fix this I can revert back to unzip on the fly.
What am I doing wrong?
I've also tried final InputStream in = response.body().source().inputStream(); with the same results. I've also tried enqueue instead of execute with the same results.
So, this is embarrassing, but I'll leave it here in case others come across a similar scenario.
The answer to my question is: "Nothing". I'm doing everything right. At least according to the above code.
What I were doing wrong though was that for debugging purposes I had logging level set to BODY, which means it has to put the whole thing in a buffer. That's also why no incremental progress was being reported.
In my app, i'm sending a file from a client, using sockets. On the other side, another client receive the file using InputStream and then bufferedOutputStream save the file in the system.
I don´t know why, the file isn´t utterly transmited. I think this is because of network overload, anyway, i don´t know how to solve it.
Transmiter is:
Log.d(TAG,"Reading...");
bufferedInputStream.read(byteArrayFile, 0, byteArrayFile.length);
Log.d(TAG, "Sending...");
bufferedOutputStream.write(byteArrayFile,0,byteArrayFile.length);
bufferedOutputStream.flush();
Receiver is:
bufferedOutputStream=new BufferedOutputStream(new FileOutputStream(file));
byteArray=new byte[fileSize];
int currentOffset = 0;
bytesReaded = bufferedInputStream.read(byteArray,0,byteArray.length);
currentOffset=bytesReaded;
do {
bytesReaded = bufferedInputStream.read(byteArray, currentOffset, (byteArray.length-currentOffset));
if(bytesReaded >= 0){ currentOffset += bytesLeidos;
}
} while(bytesReaded > -1 && currentOffset!=fileSize);
bufferedOutputStream.write(byteArray,0,currentOffset);
You don't state where filesize came from, but there are numerous problems with this code. Too many to mention. Throw it all away and use DataInputStream.readFully(). Or use the following copy loop, which doesn't require a buffer the size of the file, a technique which does not scale, assumes that the file size fits into an int, and adds latency:
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Use this at both ends. If you're sending multiple files via the same connection it gets more complex, but you haven't stated that.
This is with reference to sipdroid data encrypt failed
I tried using XOR operation instead of reverse byte code for send packets and receive packets in SipdroidSocket.class.
I experienced same issue(too much noise)
Please guide me in encrypting and decrypting packets in SipdroidSocket.class
Sorry for late reply.I am posting the snippets of the code I tried. Please refer the original RtpSocket.java and SipdroidSocket.java classes for complete view. I am just putting the snippets here.
In RtpSocket.java , I took a static value and collected the packet's header length. Then used this header length in SipdroidSocket.java so as to remove the header part prior tweaking with the payload:
In SipdroidSocket.java, following editing were done in Send and Receive functions:
public void receive(DatagramPacket pack) throws IOException {
if (loaded) {
impl.receive(pack);
byte[] b = pack.getData(); // fetch data from receiver
int len = RtpSocket.header;
pack.setData(do_something(b, len)); // do the XORing to retrieve
// original data
} else {
super.receive(pack);
byte[] b = pack.getData();
int len = RtpSocket.header;
pack.setData(do_something(b, len));
}
}
public void send(DatagramPacket pack) throws IOException {
byte[] b = pack.getData(); // fetch original data
int len = RtpSocket.header;
pack.setData(do_something(b, len)); // replace with tweaked data
if (loaded)
impl.send(pack);
else
super.send(pack);
}
private byte[] do_something(byte[] b, int len) {
// TODO Auto-generated method stub
int new_buff_len = b.length - len;
byte[] new_buff = new byte[new_buff_len];
int i = 0;
for (i = len; i < b.length; i++) // separating header values
{
new_buff[i] = (byte) (b[i] ^ 0x43); // XORing original packet
// payload before sending and
// after receiving to get
// original data on both sides
}
return new_buff;
}
Kindly , try it and suggest me please.
Finally it worked ! Had to meddle with the other parts of the code . XOR operation now works fine and have attained the objective.
I'm trying to read content from a Uri on Android, and I need the final Object type passed to the underlying SDK to by a nio.ByteBuffer.
I can get my hands on an InputStream, via ContentResolver but didn't find a way to wrap it with an nio.ByteBuffer.
Is there a way to convert a Uri content to a nio.ByteBuffer on Android?
I've ended up downloading the content of the Uri locally and open it via other method to get the ByteBuffer
Suppose you are working on an Activity,
private ByteBuffer getByteBuffer(Uri uri){
try{
InputStream iStream = getContentResolver().openInputStream(uri);
if(iStream!=null){
//value of MAX_SIZE is up to your requirement
final int MAX_SIZE = 5000000;
byte[] byteArr = new byte[MAX_SIZE];
int arrSize = 0;
while(true){
int value = iStream.read(byteArr);
if(value == -1){
break;
}else{
arrSize += value;
}
}
iStream.close();
return ByteBuffer.wrap(byteArr, 0, arrSize);
}
}catch(IOException e){
//do something
}
return null;
}
Notes:
(i) InputStream.read(byte[] b) will return an Integer which indicate total number of bytes read into the byte array b at each time.
(ii) If InputStream.read(Byte[] b) returns -1, it indicates that it is the end of the inputStream.
(iii) arrSize stores the total number of bytes read, i.e. the length of byte[] b
(iv) ByteBuffer.wrap(byte[] b, int offset, int length) will wrap the byte array to give a ByteBuffer. You may check this reference
(v) ContentResolver.openInputStream(Uri uri) and InputStream.read(byte[] b) will throw IOException so you must handle it.
(vi) Caution: IndexOutOfBoundException might happen if arrSize > MAX_SIZE, you may need to add if-else clause to handle such issue.
Please feel free to comment or change the code if there is any mistake or if there is a faster way to do that. Happy coding
Is there any way to execute Binary file in an android application. without JNI wrapper approach.
plz give me sample codes.
try this
public void pump(InputStream in, OutputStream out, int size) {
byte[] buffer = new byte[4096]; // Or whatever constant you feel like using
int done = 0;
while (done < size) {
int read = in.read(buffer);
if (read == -1) {
throw new IOException("Something went horribly wrong");
}
out.write(buffer, 0, read);
done += read;
}
// Maybe put cleanup code in here if you like, e.g. in.close, out.flush, out.close
}
from this link Reading and writing binary file in Java (seeing half of the file being corrupted)