Downloading the latest version of a file - android

I'm using the following code to download a file off a webserver that I control
URL url = new URL("http://........");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setDefaultUseCaches(false);
connection.setUseCaches(false);
connection.setRequestMethod("GET");
connection.setDoOutput("true");
connection.connect();
InputStream in = connection.getInputStream();
File dst = new File(".......");
FileOutputStream out = new FileOutputStream(dst);
byte[] buffer = new byte[1024];
int len = 0;
while ((len=in.read(buffer))>0) {
out.write(buffer,0,len);
}
connection.disconnect();
in.close();
out.close();
minus all the necessary try-catches. The above code works fine for downloading the file to my specific destination. It is however unable to download the latest version (e.g. if i change the file contents on the webserver)
it is as though the something is keeping some sort of cache of the file it downloaded before, and as long as the URL is the same as before, it sends back the same file. My data connection becomes active during the download so this might be the case at my service provider
what I need is some sort of way to force my code to proactively refresh the target file. I have found that the web-browser was able to do this. if I were to type in the link with the web-browser, and then subsequently run my code again, the latst version gets downloaded

Try to add a ?time=201211261200 at the end of URL.

Either fix it at the server, or at the client.
Client: Try to make the URL random by adding a random value. Therefore always the latest version will be downloaded.
Random r = new Random();
int someValue = r.nextInt(10000);
"http://someurl" + "?t=" + someValue;

Related

REST Server for uploading and downloading documents

I wrote an android application that part of it is to handle upload and download documents. Currently I am using the Microsoft Azure server to save the files on.
The way I am currently doing it is by turning the files to a string and saving it that way on the Azure server:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileInputStream fis;
try {
fis = new FileInputStream(new File(Uridata.getPath()));
byte[] buf = new byte[1024];
int n;
while (-1 != (n = fis.read(buf)))
baos.write(buf, 0, n);
} catch (Exception e) {
e.printStackTrace();
}
byte[] bbytes = baos.toByteArray();
item.setStringFile(Base64.encodeToString(bbytes, Base64.URL_SAFE));
item.setName(Uridata.getLastPathSegment());
where item is my class that saves the string representation and the name of the file and is being loaded to the Azure, Uridata is an Uri instance of the file chosen.
I have one main problem with this solution and it is the limit on the file size.
I am searching for a good server to use instead of the Azure (maybe a RESET one) and if there is a better way to save files of all kinds (pdf, word...).
I will also want in the future to use the same data in a web interface
Does anybody have any suggestions on how to do it?
Thanks in advance!
To start, you don't have to transform the file into a string, you can just save it as a file. You have the possibility of losing data by continuing to do that. See: How do I save a stream to a file in C#?
If you're looking for another service to save files, then you should look into Azure Blob Storage. It will allow you to upload as much data as you want to a storage service for arbitrary files. See for example:
https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-how-to-use-blobs/

Dropobx Sync API doesn't update

I'm working with the Dropbox Sync API and read in a file from dropbox, when I change the value in this file manually when my app isn't running and I start the app again, the change doesn't come through in my Android app. The value from file.readString() hasn't changed. After I restart my app several times, the changes come through. I tried dbxFs.syncNowAndWait(), file.update() and several other things to make this work. I can't seem to find the problem, after syncNowAndWait, the dropbox filesystem should "Force a check for new file info from the server" according to the documentation, but this doesn't seem to happen. Any ideas? Thanks!
dbxFs.syncNowAndWait();
DbxFile file = dbxFs.open(new DbxPath("Apps/serverIP/serverIP.txt"));
sendIPBroadcast(file.readString().split("\n")[0]);
All reads in the Sync API are from cache, and all downloads are asynchronous. So you need to open the file (which will open the cached copy from the last time you ran the app) and register a listener to be notified when a new version of the file has been downloaded. A new version will only be downloaded if you keep the file open. See https://www.dropbox.com/developers/sync/start/android#listeners for an example of how to set up a listener.
I was able to fix my problem by directly downloading the content from the dropbox URL. So I have the content immediately instead of have to wait for the updated content to be downloaded and cached. For further changes, I have a listener running.
URL url = new URL("url");
URLConnection ucon = url.openConnection();
String ip = getServerResponse(new byte[1], new DataInputStream(ucon.getInputStream()));
private String getServerResponse(byte[] b, DataInputStream in) throws IOException {
String serverSentence = "";
while(true){
in.read(b, 0, 1);
String character = new String(b, "UTF-8");
if(character.equals("*")) break;
serverSentence += character;
}
return serverSentence;
}

get size of file before download from amazon s3 in android app

I have developed an app in which I have an ASyncTask that downloads a file from Amazon s3 server.
As the related files are quite large sized, I need to show a progress bar when the download happens and a spiral progress bar doesn't look good here when it keeps rotating and irritates the user.
I need to use a horizontal style progress bar for which I need to know the size of the file to be downloaded.
Does anybody know of any way to know the file size before downloading it from amazon s3.
This is the downloading code that I have used..
#Override
protected Void doInBackground(Void... params) {
TransferManager manager = new TransferManager(access);
File file = new File(Environment.getExternalStorageDirectory()+"/Downloads", downFile);
fileDownloaded = "/Downloads/"+ downFile;
file.setWritable(true);
Download down = manager.download("files", fileToDown, file );
try {
down.waitForCompletion();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
'downFile' is the file location where I am saving it on external directory.
'fileToDown' is the file path on server that is to be downloaded.
'/Downloads/' is the new directory that I have created to store files on device.
I would assume you are using a code something like this,
URL url = new URL(f_url[0]);
URLConnection conection = url.openConnection();
// getting file length
int lengthOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
the method getContentLength() will return to you the size of the file.
UPDATE 1:
I checked the java docs of Amazon about the TransferManager and Download class. There were method and listener that might be useful to display your progress and try using them.
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Transfer.html#getProgress()
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/TransferProgress.html
getProgress() //This will return TransferProgress object. See the links above
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/transfer/Transfer.html#addProgressListener(com.amazonaws.services.s3.model.ProgressListener)
addProgressListener
This will able you I think to set up a progressListener.
UPDATE 2:
TransferProgress is an object which has bunch of informations about the progress of your download. It has bytes transferred, total bytes transferred and transfer percentage. Look at the methods detail.

Program crashes on trying to open a file

My android program crashes on this line when the file size is very large. Is there any way I can prevent the program from crashing ?
byte[] myByteArray = new byte[(int)mFile.length()];
Additional details :-
I am trying to send a file to server.
error log-
E/dalvikvm-heap(29811): Out of memory on a 136309996-byte allocation.
You should use a stream when reading the file. Since you've mentioned sending to a server, you should stream that file to the server.
As others have mentioned, you should consider your data size (1GB seems excessive). I haven't tested this, but the basic approach in code would look something like:
// open a stream to the file
FileInputStream fileInputStream = new FileInputStream(filePath);
// open a stream to the server
HttpURLConnection connection = new URL(url).openConnection();
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
byte[] buffer = new byte[BUFFER_SIZE]; // pick some buffer size
int bytesRead = 0;
// continually read from the file into the buffer and immediately write that to output stream
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer);
}
Hope that is clear enough for you to fit to your needs.
Yep. Don't try to read the whole file into memory at once...
If you really need the whole file in memory you might have more luck with allocating dynamic memory for each line and storing the lines in a list. (you might be able to get a bunch of smaller chunks of memory but not one big piece)
Without knowing the context we can't tell, but normally you would parse the file into data structs rather than just storing the whole file in memory.
In JDK 7 you can use Files.readAllBytes(Path).
Example:
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
Path path = Paths.get("path/to/file");
byte[] myByteArray = Files.readAllBytes(path);
Don't try reading the complete file into memory. Instead open a stream and process the file line by line (is it's a text file) or in parts. How that has to be done depends on the problem you are trying to solve.
EDIT: You say you want to upload a file, so please check this question. You don't need to have the complete file in memory.

Android - Download and save APK files in Phone Storage (Not in SD card)

I was trying to download one APK file from my server and save it in Phone Storage.
The following is the code that I used:
String apkLink = "http://10.1.20.53/files/test.apk";
URL url = new URL(apkLink);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
context.getDir("test.apk", Context.MODE_WORLD_WRITEABLE);
FileOutputStream fos = context.openFileOutput("app_test.apk", Context.MODE_WORLD_WRITEABLE);
InputStream is = c.getInputStream();
fileSize = c.getContentLength();
byte[] buffer1 = new byte[1024];
int len1 = 0;
int total = 0;
while ((len1 = is.read(buffer1)) != -1) {
total += len1;
percentage = (int)(total*100/fileSize);
publishProgress();
fos.write(buffer1, 0, len1);
}
fos.close();
is.close();
The same code is working fine for XML files. (When i'm downloading XML files to phone memory) .
Can someone help me with this?
Thank you
Actually I figured out the reason,
context.getDir("test.apk", Context.MODE_WORLD_WRITEABLE); code line creates a directory called "data/data/package_name/app_test.apk"
But FileOutputStream fos = context.openFileOutput("app_test.apk"); creates a directory called data/data/package_name/files/app_test.apk
And I was trying to read the file from data/data/package_name/app_test.apk directory.
Anyway, Now I am going to execute this file with this code,
File f = new File(getFilesDir()+ "/app_test.apk");
intent.setDataAndType(Uri.fromFile(f) , "application/vnd.android.package-archive");
startActivity(intent);
But it gives me a parse error message .
Any one can think of a solution?
Thank you.
Try using Context.MODE_WORLD_READABLE|Context.MODE_WORLD_WRITEABLE when you create the file.
I've answered to the similar question here. Considering your problem I have several different opinions why it is not working.
Your application download apk into its private folder and maybe PackageManager do not have permissions to read this folder. Try to download application onto sdcard and run it.
Maybe your .apk file is not properly signed. Have you signed it with your generated signature or you export file with the default test signature?
If you test this on a real device check that files can be installed from other sources (not only from Google Play market)
I do not remember precisely but maybe to call PackageManager to install an application you need a permission.

Categories

Resources