Download a file issue in android 2.3 - android

I'm using this code to download from a URL ,it works great with android 4,but in the other hand it doesn't work with android 2.3. Can someone tell what have i done wrong ?
URL url = new URL(sUrl);
URLConnection connection = url.openConnection();
connection.connect();
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(pathFolder+"/"+fileName);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();

It works for me. Here is my method:
private boolean dowloadFile(String url, File saveFile) {
int BUFF_SIZE = 1024 * 1024; //1Mo
long length = 0;
long current = 0;
if(saveFile.exists())
current = saveFile.length();
try {
DefaultHttpClient http = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
if(current>0)
request.addHeader("Range", "bytes=" + current + "-");
HttpResponse response = http.execute(request);
if (response.getStatusLine().getStatusCode() != 200 && response.getStatusLine().getStatusCode() != 206) {
return false;
}
Header[] headers = response.getHeaders("Content-Range");
if(headers.length>0) {
String s = headers[0].getValue();
length = Integer.valueOf(s.subSequence(s.indexOf("/")+1, s.length()).toString());
} else {
Header[] headers2 = response.getHeaders("Content-Length");
if(headers2.length>0)
length = Integer.valueOf(headers2[0].getValue());
if(current>0) {
saveFile.delete();
current = 0;
}
}
BufferedInputStream ls = new BufferedInputStream(response.getEntity().getContent());
long nexttime = 0;
RandomAccessFile fos = new RandomAccessFile(saveFile, "rw");
fos.seek(current);
byte[] buffer = new byte[BUFF_SIZE];
while (current < length) {
boolean buffFull = false;
int currentBuff = 0;
int readSize = 0;
while (buffFull == false) {
readSize = ls.read(buffer, currentBuff, BUFF_SIZE - currentBuff);
if (readSize == -1)
buffFull = true;
else {
currentBuff += readSize;
if (currentBuff == BUFF_SIZE)
buffFull = true;
}
}
fos.write(buffer, 0, currentBuff);
current += currentBuff;
long time = SystemClock.elapsedRealtime();
if (nexttime < time) {
// Progress
nexttime = time + 1000;
}
}
fos.close();
// Progress Finish
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}
I hope I have helped you !

Related

How to update UI with download progress when download is a runnable being executed in a ThreadpoolExecutor?

I am implementing a download manager in native android where a thread pool executor is used to implement parallel downloads. A runnable is where the actual download happens, which is being executed on the pool threads. How can I send the download progress from the runnable to the UI? In order to send broadcasts, I need to pass context into the runnable. Is that the appropriate way?
How can I handle pause/resume/cancel of download gracefully?
Right now the moment user taps the pause/cancel button the value is updated in the DB and while the Thread.CurrentThread().IsInterrupted condition in the runnable becomes valid I check the status in database and decide whether I need to delete the partially downloaded file (if its cancel).
Also, will it be possible to know when the download completes so that I can remove the future object from the list?
public class Downloadable : Java.Lang.Object, IRunnable
{
private readonly string _destination;
private readonly int _productId;
public Downloadable(int productId)
{
_productId = productId;
_destination = Utils.StoragePath() + productId + ".zip";
}
public void Run()
{
int count;
try
{
Response response = CloudService.GetCloud().GetDownLoadURL(_productId.ToString(), true).Result;
if (string.Equals(response.status, "error", StringComparison.OrdinalIgnoreCase) || string.Equals(response.status, "internalError", StringComparison.OrdinalIgnoreCase))
{
//send error
}
else
{
DownloadPath downloadPath = JsonConvert.DeserializeObject<DownloadPath>(response.data);
string offlineUrl = downloadPath.contentUrl.Offline;
if (string.IsNullOrWhiteSpace(offlineUrl))
{
//send error
}
else
{
File directory = new File(Utils.StoragePath());
if (!directory.Exists())
directory.Mkdirs();
URL url = new URL(offlineUrl);
HttpURLConnection connection = (HttpURLConnection)url.OpenConnection();
long total = 0;
File file = new File(_destination);
file.CreateNewFile();
if (file.Exists() && file.Length() > 0)
{
total = file.Length();
connection.SetRequestProperty("Range", "Bytes=" + total + "-");
}
connection.Connect();
int lenghtOfFile = connection.ContentLength;
BufferedInputStream bufferedInputStream = new BufferedInputStream(url.OpenStream());
FileOutputStream fileOutputStream = new FileOutputStream(_destination, true);
byte[] buffer = new byte[1024];
count = 0;
while ((count = bufferedInputStream.Read(buffer, 0, 1024)) != -1)
{
if (Thread.CurrentThread().IsInterrupted)
{
if (DBService.GetDB().GetStatus(_productId) == (int)IpcCommon.Enumerations.Status.DOWNLOAD)
file.Delete();
break;
}
total += count;
System.Console.WriteLine("__PROGRESS__ " + (int)((total * 100) / lenghtOfFile));
System.Console.WriteLine("__PROGRESS__ ID " + _productId);
//publishProgress("" + (int)((total * 100) / lenghtOfFile));
fileOutputStream.Write(buffer, 0, count);
}
fileOutputStream.Close();
bufferedInputStream.Close();
}
}
}
catch (System.Exception exception)
{
IpcCommon.App.Logger.Log("Downloadable - File Download", new System.Collections.Generic.Dictionary<string, string> { { "Error", exception.Message } });
}
}
}
Dictionary<int, IFuture> _runningTaskList = new Dictionary<int, IFuture>();
int noOfCores = Runtime.GetRuntime().AvailableProcessors();
LinkedBlockingQueue _taskQueue = new LinkedBlockingQueue();
_threadPoolExecutor = new ThreadPoolExecutor(noOfCores, noOfCores * 2, 1, TimeUnit.Minutes, _taskQueue);
IFuture future = _threadPoolExecutor.Submit(new Downloadable(productId));
_runningTaskList.Add(productId, future);

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);

Asynctask fast on virtual device, slow on real device

I am using a service to download files and extract them if they are archived.
The extraction method is wrapped as a asynctask to improve performance of the extraction process.
My problem is that when I run the app on the virtual device, all is fine and the extraction process is really fast but as soon as I test it on a real device (Nexus 9 tablet, Android 6x) the extraction process is really slow and takes minutes to complete.
Is there anything I can do, to speed up the extraction process?
I execute the asynctask with: new UnRarTask(targetAppName).execute();
Below the piece of code which is relevant:
public class DownloadTask implements Runnable {
private DownloadService service;
private DownloadManager downloadManager;
protected void init(DownloadService service, Intent intent) {
this.service = service;
downloadManager = (DownloadManager) MyApp_.getInstance().
getSystemService(Activity.DOWNLOAD_SERVICE);
DownloadRequest downloadRequest = intent.getParcelableExtra(DownloadService
.DOWNLOAD_REQUEST);
}
private class UnRarTask extends AsyncTask<Void, Integer, String> {
String rarPath = null;
int countRar = 0;
long copiedbytes = 0, totalbytes = 0;
Archive archive = null;
FileHeader fileHeader = null;
File archiveFile;
List<FileHeader> headers;
UnRarTask(String one) {
this.archiveFile = new File(one);
}
#Override
protected String doInBackground(Void... params) {
try {
archive = new Archive(new FileVolumeManager(archiveFile));
} catch (RarException | IOException e) {
e.printStackTrace();
}
String fileName = archiveFile.getName();
String absolutePath = archiveFile.getAbsolutePath();
String archiveDirectoryFileName = absolutePath.substring(0, absolutePath.indexOf(fileName));
if (archive != null) {
fileHeader = archive.nextFileHeader();
headers = archive.getFileHeaders();
for (FileHeader fh : headers) {
totalbytes = totalbytes + fh.getFullUnpackSize();
}
}
while (fileHeader != null) {
BufferedInputStream inputStream;
try {
inputStream = new BufferedInputStream(archive.getInputStream(fileHeader));
String extractedFileName = fileHeader.getFileNameString().trim();
String fullExtractedFileName = archiveDirectoryFileName + extractedFileName;
File extractedFile = new File(fullExtractedFileName);
FileOutputStream fileOutputStream = new FileOutputStream(extractedFile);
BufferedOutputStream flout = new BufferedOutputStream(fileOutputStream, BUFFER_SIZE);
if (extractedFile.getName().toLowerCase().endsWith(".mp3")
|| extractedFile.getName().toLowerCase().endsWith(".epub")
|| extractedFile.getName().toLowerCase().endsWith(".pdf")
|| extractedFile.getName().toLowerCase().endsWith(".mobi")
|| extractedFile.getName().toLowerCase().endsWith(".azw3")
|| extractedFile.getName().toLowerCase().endsWith(".m4b")
|| extractedFile.getName().toLowerCase().endsWith(".apk")) {
rarPath = extractedFile.getPath();
countRar++;
}
int len;
byte buf[] = new byte[BUFFER_SIZE];
while ((len = inputStream.read(buf)) > 0) {
//fileOutputStream.write(buf, 0, len);
copiedbytes = copiedbytes + len;
int progress = (int) ((copiedbytes / (float) totalbytes) * 100);
if (progress > lastProgress) {
lastProgress = progress;
service.showUpdateProgressNotification(downloadId, appName, progress,
"Extracting rar archive: " + lastProgress + " % completed", downloadStart);
}
}
archive.extractFile(fileHeader, flout);
flout.flush();
flout.close();
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
fileHeader = archive.nextFileHeader();
} catch (RarException | IOException e) {
e.printStackTrace();
}
}
if (countRar == 0) {
filePath = "Error";
broadcastFailed();
}
if (copiedbytes == totalbytes) {
if (archive != null)
archive.close();
}
return null;
}
}
}

Android calculate download speed test

I am trying to calculate a download speed test calculate.
Found a lot info in Stackoverflow but nothing help me.
The final calculation is not logic.
Trying to know the download speed in the while thread.
Attached my code that I found.
public void run() {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try
{
URL url1 = new URL("test");
out = new BufferedOutputStream(new FileOutputStream(getVideoFile().getPath()));
conn = url1.openConnection();
in = conn.getInputStream();
long start = System.currentTimeMillis();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1)
{
out.write(buffer, 0, numRead);
numWritten += numRead;
long end = System.currentTimeMillis();
if ((end - start)>0) {
double rate = 1000f * numWritten / (end - start) ;
Log.d("downloadmanager","speed "+rate);
}
}
}
catch (Exception ex)
{
Log.d("downloadmanager","Unknown Error: " + ex);
}
finally
{
try
{
if (in != null)
{
in.close();
}
if (out != null)
{
out.close();
}
}
catch (IOException ex)
{
Log.d("downloadmanager", "Unknown Error: " + ex);
}
}
}
}).start();
Thanks for helping figure this up.
I have tried like this way, hope it will help!
The change is , I have used set of url's.
public class TestSpeed extends AsyncTask<Void,Void,Void> {
String TAG = "TestSpeed";
long startTime,endTime,contentLength;
String vURL[] = {
"http://test/url/file1",
"http://test/url/file2",
"http://test/url/file3",
"http://test/url/file4",
"http://test/url/file5",
"http://test/url/file6",
"http://test/url/file7"
"http://test/url/file8"
};
#Override
protected Void doInBackground(Void... params) {
setCall(vURL[GlobalData.URLIndex]);
GlobalData.URLIndex += 1;
if(GlobalData.URLIndex >= vURL.length){
GlobalData.URLIndex = 0;
}
return null;
}
void setCall(String URL){
try {
Log.d(TAG,"Start " + URL);
startTime = System.currentTimeMillis(); //Hold StartTime
HttpGet httpRequest = new HttpGet(new URL(URL).toURI());
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpClient.execute(httpRequest);
endTime = System.currentTimeMillis(); //Hold EndTime
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity;
bufHttpEntity = new BufferedHttpEntity(entity);
//You can check the size of your file
contentLength = bufHttpEntity.getContentLength();
// Log
Log.d("TAG", "Dowload time :" + (endTime - startTime) + " ms");
// Speed : size(KB)/time(s)
Long mSpeed = contentLength / ((endTime - startTime) * 1000);
Log.d(TAG, "mSpeed :" + mSpeed);
Double duration = Double.valueOf((endTime - startTime));
Double speedKbps = Double.valueOf(roundTwoDecimals(Double.valueOf(contentLength / 1024)));
Double speedMbps = roundTwoDecimals(speedKbps / 1024);
Log.d(TAG,"" + speedKbps);
Log.d(TAG,"" + speedMbps);
//confirm units for display
String mTheSpeed = "" + speedMbps;
String speed;
if(mTheSpeed.charAt(0) == '0'){
speed = roundTwoDecimals(speedKbps) + " kb/s";
}else{
speed = roundTwoDecimals(speedMbps) + " mb/s";
}
Log.d("Speed Result: ","" + speed);
}catch (Exception ex){
ex.printStackTrace();
}
}
Double roundTwoDecimals(Double vLongValue)
{
DecimalFormat twoDForm = new DecimalFormat("#.###");
return Double.valueOf(twoDForm.format(vLongValue));
}
}
For an alternative you can go with the WifiInfo, the code looks like this.
private static Integer wifiSpeed(Context mContext){
WifiManager wifiManager = (WifiManager);
mContext.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
Integer wifiSpeed = wifiInfo.getLinkSpeed();
return wifiSpeed;
}

Android check download successful

For downloading stuff I work with the apache classes HTTPResponse HTTPClient etc.
I check for a valid download like this:
entity.writeTo(new FileOutputStream(outfile));
if(outfile.length()!=entity.getContentLength()){
long fileLength = outfile.length();
outfile.delete();
throw new Exception("Incomplete download, "+fileLength+"/"
+entity.getContentLength()+" bytes downloaded");
}
But it seems that the exception is never triggered. How to properly handle this? Is entity.getContentLength the length of the file on server or the amount of data received?
The file request should always come with a MD5 checksum. If you have an MD5 header then all you need to do is check that against the files generated MD5. Then your done, its better to do it this way as you can have a file with the same number of bytes but one byte gets garbled in transmission.
entity.writeTo(new FileOutputStream(outfile));
String md5 = response.getHeaders("Content-MD5")[0].getValue();
byte[] b64 = Base64.decode(md5, Base64.DEFAULT);
String sB64 = IntegrityUtils.toASCII(b64, 0, b64.length);
if (outfile.exists()) {
String orgMd5 = null;
try {
orgMd5 = IntegrityUtils.getMD5Checksum(outfile);
} catch (Exception e) {
Log.d(TAG,"Exception in file hex...");
}
if (orgMd5 != null && orgMd5.equals(sB64)) {
Log.d(TAG,"MD5 is equal to files MD5");
} else {
Log.d(TAG,"MD5 does not equal files MD5");
}
}
Add this class to your project:
public class IntegrityUtils {
public static String toASCII(byte b[], int start, int length) {
StringBuffer asciiString = new StringBuffer();
for (int i = start; i < (length + start); i++) {
// exclude nulls from the ASCII representation
if (b[i] != (byte) 0x00) {
asciiString.append((char) b[i]);
}
}
return asciiString.toString();
}
public static String getMD5Checksum(File file) throws Exception {
byte[] b = createChecksum(file);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
public static byte[] createChecksum(File file) throws Exception {
InputStream fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}
}

Categories

Resources