How to update progressbar at 10 percent increments? - android

I have a service running that uploads photos. Currently it's updating the progressbar every one percent. 1%...2%..3%...
How would I update it only at increments of 10%?
#Override
public void writeTo(#NonNull BufferedSink sink) throws IOException {
long fileLength = mFile.length();
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
FileInputStream in = new FileInputStream(mFile);
long uploaded = 0;
int read;
while ((read = in.read(buffer)) != -1) {
int percent = (int) (100 * uploaded / fileLength);
//Update progress bar
mManager.notify(NOTIFICATION_ID, uploadingProgressNotification(String.valueOf(current_image_uploading), percent));
uploaded += read;
sink.write(buffer, 0, read);
}
}

you can try this piece of code
int percent = 10 * (int) (10 * uploaded / fileLength);
dividing by 10 and casting to int will discard the decimal place for the digits.
you then multiply it by 10 to give you increments in steps of 10s.

Related

How to start play .mkv and .mp4 videos on Mi Video using NanoHttpd without reading the entire file (Android)

I'm using NanoHttpd library in order to serve video files of type .mkv and .mp4 on Mi Video.
As the reading of the input stream was too slow, I changed NanoHttpd's reading buffer size to 1M:
private void sendBody(OutputStream outputStream, long pending) throws IOException {
long BUFFER_SIZE = 1048576L; // Instead of 16384
byte[] buff = new byte[(int)BUFFER_SIZE];
boolean sendEverything = pending == -1L;
while(pending > 0L || sendEverything) {
long bytesToRead = sendEverything ? BUFFER_SIZE : Math.min(pending, BUFFER_SIZE);
int read = this.data.read(buff, 0, (int)bytesToRead);
if (read <= 0) {
break;
}
outputStream.write(buff, 0, read);
if (!sendEverything) {
pending -= (long)read;
}
}
}
I changed inputStream.skip() the same way:
public long skip(long n) throws IOException {
long remaining = n;
int nr;
if (n <= 0) {
return 0;
}
int size = (int)Math.min(1048576L, remaining); \\ Instead of 2048
byte[] skipBuffer = new byte[size];
while (remaining > 0) {
nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
if (nr < 0) {
break;
}
remaining -= nr;
}
return n - remaining;
}
I override NanoHttpd.serve():
#Override
public Response serve(IHTTPSession session) {
... // Getting the inputStream, length and mimeType
String range = null;
for (String key : session.getHeaders().keySet()) {
if ("range".equals(key)) {
range = session.getHeaders().get(key);
}
}
if (null != range) {
return createPartialResponse(mimeType, inputStream, length, range);
} else {
return createFullResponse(mimeType, inputStream, length);
}
}
private Response createFullResponse(String mimeType, InputStream inputStream, long length) {
return newFixedLengthResponse(Response.Status.OK, mimeType, inputStream, length);
}
private Response createPartialResponse(String mimeType, InputStream inputStream, long length, String rangeHeader) throws IOException {
Response response = null;
String rangeValue = rangeHeader.trim().substring("bytes=".length());
long lastIndex = length - 1;
long startIndex, endIndex;
if (rangeValue.startsWith("-")) { // Range: bytes=-<suffix-length>
endIndex = lastIndex;
startIndex = lastIndex - Long.parseLong(rangeValue.substring("-".length()));
} else { // Range: bytes=<range-start>- OR bytes=<range-start>-<range-end> OR bytes=<range-start>-<range-end>, <range-start>-<range-end>
String[] range = rangeValue.split("-");
startIndex = Long.parseLong(range[0]);
endIndex = range.length > 1 ? Long.parseLong(range[1]) : lastIndex;
}
if (endIndex > lastIndex) {
endIndex = lastIndex;
}
if (startIndex <= endIndex) {
long newLength = endIndex - startIndex + 1;
inputStream.skip(startIndex);
response = newFixedLengthResponse(Response.Status.PARTIAL_CONTENT, mimeType, inputStream, newLength);
response.addHeader("Content-Length", String.valueOf(newLength));
response.addHeader("Content-Range", "bytes " + startIndex + "-" + endIndex + "/" + length); // "bytes start-end/length"
} else {
response = newFixedLengthResponse(Response.Status.RANGE_NOT_SATISFIABLE, MIME_PLAINTEXT, rangeHeader);
response.addHeader("Content-Range", "bytes 0-0/" + length); // "bytes 0-0/length"
}
response.addHeader("Accept-Ranges", "bytes"); // Announce that the file server accepts partial content requests
return response;
}
With Mi Video, small sizes of .mkv (98.5 MB) and .mp4 (77.9 MB) had to be read completely before they could be played (~15 seconds). But, large file sizes of nearly 1GB were played without reading the whole file.
I want to play both .mp4 and .mkv files with Mi Video without reading the whole file at the beginning no matter the size of the file.

How to only call NotificationManager at 10% increments

I have a service running that uploads photos. I have a progressbar that is updated by NotificationManager, however its being called multipletimes.
IntentService[n identical 127 lines
How can I make it so that the manager only notifies when increments of 10% are uploaded?
#Override
public void writeTo(#NonNull BufferedSink sink) throws IOException {
long fileLength = mFile.length();
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
FileInputStream in = new FileInputStream(mFile);
long uploaded = 0;
int read;
while (is_uploading && (read = in.read(buffer)) != -1) {
int percent = 10* (int) (10 * uploaded / fileLength);
mManager.notify(NOTIFICATION_ID, uploadingProgressNotification(String.valueOf(current_image_uploading+1), percent + 10));
uploaded += read;
sink.write(buffer, 0, read);
}
}
Edit:
#Override
public void writeTo(#NonNull BufferedSink sink) throws IOException {
long fileLength = mFile.length();
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
FileInputStream in = new FileInputStream(mFile);
long uploaded = 0;
int read;
while (is_uploading && (read = in.read(buffer)) != -1) {
int percent = 10* (int) (10 * uploaded / fileLength);
if(percent % 10 == 0){
Log.d(TAG, "writeTo: test");
mManager.notify(NOTIFICATION_ID, uploadingProgressNotification(String.valueOf(current_image_uploading+1), percent + 10));
}
uploaded += read;
sink.write(buffer, 0, read);
}
}
The Log.d(TAG, "writeTo: test"); is still being called many times even though it should only be 10 times.
IntentService[n identical 346 lines
Use below code:
int percent = (int) (100 * uploaded / fileLength);
if(percent % 10 == 0 && lastPercent != percent){
lastPercent = percent;
mManager.notify(NOTIFICATION_ID, uploadingProgressNotification(String.valueOf(current_image_uploading+1), percent));
}
also create globle variable public int lastPercent = 0;

I am converting a video file to string using Base64.encodeToString, but I want to do it in several parts to avoid out of memory error

This is my code, but the second split of the video is different, therefore when combining the split parts the video plays the first split but the second part it does not.
int bufferSize = (int) video_size_bytes;
byte[] buffer = new byte[bufferSize];
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int len = 0;
try {
while ((len = inputStream.read(buffer)) != -1)
{
byteBuffer.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
Log.i(PostsActivity.TAG, "IOException: " + e.getMessage());
}
int offset = 0;
int addition = 100000;
int length = 100000;
int limit = (int) video_size_bytes;
boolean stop_loop = false;
boolean loop_mock = true;
do{
//Converting bytes into base64
String video_string_raw = Base64.encodeToString(byteBuffer.toByteArray(), offset, length, Base64.DEFAULT);
String video_string_raw_refined = video_string_raw.trim();
video_string = video_string_raw_refined.replaceAll("\n", "");
video_parts_array_string.add(video_string);
if(stop_loop){
break;
}
offset = offset + addition;
if((offset+addition) > limit){
length = limit-offset;
stop_loop = true;
}else{
offset = offset + addition;
}
}while(loop_mock);

retrofit call execute using rxjava

Scenario :
Create request
**Interface**
#GET("someurl.mp4")
#Streaming
Call<ResponseBody> downloadFile(); // retrofit2.Call
**call**
RetrofitInterface retrofitInterface = retrofit.create(RetrofitInterface.class);
//okhttp3.ResponseBody
Call<ResponseBody> request = retrofitInterface.downloadFile();
try {
downloadFile(request.execute().body());
} catch (IOException e) {
e.printStackTrace();
}
Download bytes by bytes
private void downloadFile(ResponseBody body) throws IOException {
int count;
byte[] data;
data = new byte[1024 * 4];
long fileSize = body.contentLength();
Log.i("Download", "downloadFile: " + fileSize);
InputStream bis = new BufferedInputStream(body.byteStream(), 1024 * 8);
File outputFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), System.currentTimeMillis() + ".mp4");
try (OutputStream output = new FileOutputStream(outputFile)) {
long total = 0;
long startTime = System.currentTimeMillis();
Log.i("Download", "downloadFile size: " + fileSize);
int timeCount = 1;
while ((count = bis.read(data)) != -1) {
total += count;
totalFileSize = (int) (fileSize / (Math.pow(1024, 2)));
double current = Math.round(total / (Math.pow(1024, 2)));
int progress = (int) ((total * 100) / fileSize);
long currentTime = System.currentTimeMillis() - startTime;
Download download = new Download();
download.setTotalFileSize(totalFileSize);
if (currentTime > 1000 * timeCount) {
download.setCurrentFileSize((int) current);
download.setProgress(progress);
sendNotification(download);
timeCount++;
}
if (download.getProgress() != 0)
Log.i("Download", "progress: " + download.getProgress());
output.write(data, 0, count);
}
onDownloadComplete();
output.flush();
//output.close();
}
bis.close();
}
Problem
I am not able to port above code in RxJava using Observable/Single interface.
All i want is to download file bytes by bytes for some purpose.
I tried to call downloadFile(request.execute().body()); inside ongoing async operation(RxJava) but didn't work as expected.
There is no good reason to declare method as returning Call<ResponseBody> if you are using RxJava anyway. Declare it as Single<ResponseBody> and use its result directly.

Getting lseek failed: EBADF (Bad file number) Exception in reading bitmap from InputStream

I'm getting " lseek failed: EBADF (Bad file number) exception" issue while creating the bitmap from InputStream. This issue is occuring in some specific devices only. for me I'm getting this error in "Nexus 5" device and my client getting this issue in "Samsung S3" device. I'm not getting the issue in my Samsung s3 device. The question is similar to link1 and
link2
But I'm unable to debug and fix this issue. Below is my code in reading the Input stream and bitmap.
InputStream in = getImageStream(index);
public InputStream getRawImageStream(long position) throws IOException {
super.seek(position);
long length = super.readLong();
LOG.debug("getRawImageStream(0x%x) len:%,d", position, length);
if (length > MAX_IMAGE_SIZE) {
throw new IOException(String.format("Excessive image length %,d", length));
}
return new RandomAccessFileInputStream(this, length);
}
public static long copy(InputStream input, OutputStream output, long length) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
long count = 0;
int n = 0;
int chunk = BUFFER_SIZE;
while (count < length) {
if (count + chunk > length) {
chunk = (int) (length - count);
}
if (-1 == (n = input.read(buffer, 0, chunk))) {
break;
}
output.write(buffer, 0, n);
count += n;
}
return count;
}
#Override
public int read(byte[] b, int off, int len) throws IOException {
long alen = Math.min(len, endPosition - file.getFilePointer());
if (len <= 0) {
// At end of stream / section
return END_OF_SECTION;
}
return this.file.read(b, off, (int) alen);
}
Please check my code and let me know your thoughts.Any help would be highly appriciated.

Categories

Resources