My app needs to download a database from the internet. This is done in an AsyncTask so when the database is being downloaded it't is being shown a Progress Dialog.
This is the code for the database download:
public void downloadDB(String dbFile, String dbFileName) {
int count;
try {
URL url = new URL(dbFile);
URLConnection conection = url.openConnection();
conection.connect();
InputStream input = new BufferedInputStream(url.openStream(), 8192);
OutputStream output = new FileOutputStream(ctx.getApplicationInfo().dataDir + "/databases/" + dbFileName);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
} catch (IOException e) {
Log.e("Error: ", e.getMessage());
}
}
}
I'm doing some tests and when the database is being downloaded I turn off the internet connection. The problem is that the Progress Dialog doesn't terminate (it's in an infinite loop). I was expecting that after turning off the internet, there would be the IOException, the function returned to the doInBackground method of AsyncTask and executed the onPostExecute method where I dismiss the Progress Dialog.
The strange thing is that if I have my phone disconnected from the computer, the progress dialog is never dismissed, the same thing if I'm running the app with phone connected to computer and looking at the log cat. If I enter debug mode, the downloadDB ends and is returned to the caller and then, the progress dialog is dismissed.
What can I do to return from the downloadDB function when the network is turned off?
Related
I need to download a few large zip files into my application (each approx 25mb) however it seems quite slow (5 minutes +) and when we test the same files being downloaded on an iPad it's downloading several times faster. I've considered using Volley, however it seems asynctask is the best for large files (from what I've read).
Does anyone have any suggestions or ideas on how I might be able to download/write these files faster?
My current implementation is show below:
My AsyncTaskExample:
#Override
protected String doInBackground(String... sUrl) {
InputStream input = null;
OutputStream output = null;
HttpURLConnection connection = null;
try {
URL url = new URL(sUrl[0]);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
// expect HTTP 200 OK, so we don't mistakenly save error report
// instead of the file
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server returned HTTP " + connection.getResponseCode()
+ " " + connection.getResponseMessage();
}
// this will be useful to display download percentage
// might be -1: server did not report the length
int fileLength = connection.getContentLength();
// download the file
input = connection.getInputStream();
output = new FileOutputStream("/sdcard/file_name.extension");
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
// allow canceling with back button
if (isCancelled()) {
input.close();
return null;
}
total += count;
// publishing the progress....
if (fileLength > 0) // only if total length is known
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
} catch (Exception e) {
return e.toString();
} finally {
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
}
if (connection != null)
connection.disconnect();
}
return null;
}
AsyncTask should be used only for relatively short background processes (i.e. processes that last a few seconds). From the docs:
AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent package such as Executor, ThreadPoolExecutor and
FutureTask.
For long operations you should use a Service:
A Service is an application component representing either an
application's desire to perform a longer-running operation while not
interacting with the user or to supply functionality for other
applications to use.
I have a SQLite database file in my server, and from time to time my Android App checks if there is a new SQLite database file. If true the App downloads the File and replaces the old database.
The problem is, that some times the new database file gets corrupted and the App start to crashing and never recovers if I dont manualy clean the app in the Android Settings.
My question is, there is a way to check the integrity of SQLite Database after the Downloaded?
This is my code for download the new Database from the server this code is placed in an AssyncTask :
protected Boolean doInBackground(String... Url) {
try {
URL url = null;
if(Url[0].equals("")){
mSyncDate = mConnectionManager.getSyncDate();
url = new URL(Constants.HF_SERVER_DATABASE+"db_fxbus_"+convertDateToFormatYYYYMMDD(mSyncDate.getServerDate())+".sqlite");
}else{
url = new URL(Url[0]);
}
URLConnection connection = url.openConnection();
connection.connect();
// this will be useful so that you can show a typical 0-100% progress bar
int fileLength = connection.getContentLength();
mDB.getReadableDatabase();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
Log.i(TAG, "Path:"+mContext.getDatabasePath("HorariosDoFunchal").getAbsolutePath());
OutputStream output = new FileOutputStream(mContext.getDatabasePath("HorariosDoFunchal").getAbsolutePath());
startWriting = true;
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);
//Log.i(TAG, "Executing ...");
}
//Log.i(TAG, "Finish ...");
output.flush();
output.close();
input.close();
} catch (Exception e) {
Log.e(TAG, e.toString());
return false;
}
return true;
}
Look into:
pragma integrity_check;
it will scan the Database and check it for errors and other things too.
More info(and more commands) can be found at this link:
http://www.sqlite.org/pragma.html
also check out the documentation of isDatabaseIntegrityOk().
You could try to use PRAGMA integrity_check (or Android's equivalent isDatabaseIntegrityOk()), but this checks only the database structure for errors, and can detect only errors where it can prove that the structure is wrong.
To be able to detect all errors (especially in your own data), you need to compute a checksum for the entire database file.
I'm new to Android and developing a file downloading app with a ProgressDialog which shows the downloading percentage.
I use AsyncTask and here is the trouble part of my code.
protected String doInBackground(String... f_url){
int count;
try {
URL url = new URL(f_url[0]);
URLConnection conn = url.openConnection();
conn.connect();
// getting file length
int lenghtOfFile = conn.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
File direct = new File(folder);
if(!direct.exists()) {
direct.mkdirs();
}
// Output stream to write file
OutputStream output = new FileOutputStream(apkPath);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
// After this onProgressUpdate will be called
publishProgress(""+(int)((total*100)/lenghtOfFile));
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
return null;
}
My issue is this code works really well on Android API 16 (JB) but not on API 19 (KitKat). On KitKat devices, the progress bar percentage does not update (always 0). After checking the codes, I found conn.getContentLength() returns -1 when I run it on KitKat. So it can not update the progress. But it returns correct file size when I run it on API 16 (JB).
Can somebody please help me to solve this?
Thank you in advance.
Have you read Migrating to WebView in Android 4.4: http://developer.android.com/guide/webapps/migrating.html
Blockquote
If you call methods on WebView from any thread other than your app's UI thread, it can cause unexpected results. For example, if your app uses multiple threads, you can use the runOnUiThread() method to ensure your code executes on the UI thread:
runOnUiThread(new Runnable() {
#Override
public void run() {
// Code for WebView goes here
}
});
You can try this:
conn.setRequestProperty("Accept-Encoding", "identity");
I have an application that downloads multiple files (and checks the download speed) within an Asynctask. However, when I am connected to 3G (and there is a handover) or the device switches form WiFi to 3G, my application freezes and I can not handle this problem
#Override
protected Integer doInBackground(String... sUrl) {
try {
speed=0; //initial value
int i=0;
while ((i<sUrl.length)) {
URL url = new URL(sUrl[i]);
URLConnection connection = url.openConnection();
connection.setReadTimeout(10000);
connection.connect();
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(file);
byte data[] = new byte[1024*1024]; //1MB buffer
long total = 0;
int count;
long start = System.currentTimeMillis();
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
long finish = System.currentTimeMillis();
long tempSpeed= (fileLength *8)/(finish-start);
if (tempSpeed>speed) {
speed=tempSpeed;
}
output.flush();
output.close();
input.close(); // connection is closed
i++;
}
}catch(SocketTimeoutException e) {
exceptions.add(e);
messageProgressDialog.setCancelable(true);
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(gui.getActivity()).create();
alertDialog.setTitle("Network problem");
alertDialog.setMessage("connection dropped");
alertDialog.show();
} catch (IOException e) {
exceptions.add(e);
messageProgressDialog.setCancelable(true);
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(gui.getActivity()).create();
alertDialog.setTitle("IOException");
alertDialog.setMessage("IOException error");
alertDialog.show();
} catch(Exception e) {
exceptions.add(e);
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(gui.getActivity()).create();
alertDialog.setTitle("Exception");
alertDialog.setMessage("Exception error");
alertDialog.show();
}
return 1;
}
I have read many topics on stackoverflow, however none of them could help me solve the prolem I have with my application. I have the try/catch clause, but it doesn't seem to make a difference. When I am using 3G and the phone connects to annother antenna, or there is a network problem the application freezes. What can I do ?
I have found the problem. It was this line InputStream input = new BufferedInputStream(url.openStream()); I use as inputstream the url. I replaced it with this line: InputStream input = new BufferedInputStream(connection.getInputStream()); Now it seems to work better, when it times-out, the application crashes.
}catch(SocketTimeoutException e) {
String erro=Integer.toString(count);
Log.d("error socketTimeout",erro);//1st log
exceptions.add(e);
onPostExecute(1);
Log.d("error sockteTimeout", "here"); //2nd log to see if onPostExecute worked
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(gui.getActivity()).create();
alertDialog.setTitle("Network problem");
alertDialog.setMessage("connection dropped");
alertDialog.show();
This is the catch that I use. It seems that when I try to call the within the catch clause the onPostExecute method my application crashes.
protected void onPostExecute(Integer result) {
Log.d("onpost was called", "here");
messageProgressDialog.setMessage("Your speed is: " + speed +" KBit/sec");
messageProgressDialog.setCancelable(true);
}
Looking on the Log viewer, only the 1st Log appears. When onPostExecute is called, the app crashes. onPostExecute is never actually executed.
Any ideas?
Your problem is likely related to your handling of the return value of input.read(). If a socket is closed, input.read() may return 0 (it may also return -1 in other error situations). If it does return 0, then your loop will hang. I suggest something like:
while ((count = input.read(data)) > 0) {
That way, your loop will run while you are still making progress on the download.
I try to create an application that can download files from a server in order to measure the speed that I can get with the particular server. I do this by using the Asynctask class. All the files that I want to download are located on the same directory. My question is, how can I download the subsequent files by keeping the connection and not by creating every time a new one? I know that for a TCP connection, there must be a 3-way-handshake established, before downloading a file. I want to connect to the server and then keep the connection and perform the download.
My code looks like this
#Override
protected Integer doInBackground(String... sUrl) {
try {
speed=0; //initial value
int i=0;
while ((i<sUrl.length)) {
URL url = new URL(sUrl[i]); //sUrl[] contains the links that i want
// for example http://myserver.net/file1.jpg, http://myserver.net/file2.jpg ... etc
URLConnection connection = url.openConnection();
connection.connect(); //connection to be established 3WAY HANDSHAKE
int fileLength = connection.getContentLength();
// download the file
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(file);
byte data[] = new byte[1024];
long total = 0;
int count;
long start = System.currentTimeMillis();
while ((count = input.read(data)) != -1) {
total += count;
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
long finish = System.currentTimeMillis();
long tempSpeed= (fileLength *8)/(finish-start);
if (tempSpeed>speed) {
speed=tempSpeed;
}
output.flush();
output.close();
input.close(); // connection is closed
i++;
}
}catch(Exception e) {
exceptions.add(e);
}
return 1;
}
By creating a new connection I loose time (for the download speed), because of the 3way handsharke . Also when transfering files in TCP, there is something called a tcp window (when you dowload data, initialy you start with low speed transmission, and if the connection is good this rate increases).
How can I do the above without creating and tearing down the connection for each file?
Looking at you code, you keep receiving until the socket is close at the other side, so there is no way of using the same socket since it's closed. If you can program both, the server and the client, then, I would suggest one possible way of doing it, and that is with a protocol, instead of receiving the file directly, the first packet you get is an integer which indicates the size of the file you're going to receive. If that length is 0 (cero) it means there no more files and the connection should be closed.
At the server:
While (the_are_files_to_send)
{
Socket.write((int) FileSize);
Socket.write(file's content);
}
Socket.Write(0); // No more files;
Socket.Close();
At the Client:
While ((size = Socket.read(buffer, 0, 4)) != -1)
{
int FileLength = convert_to _int(buffer);
if (FileLength==0) break;
Socket.read(FileLength bytes);
}
Socket.Close();