Téléchargement fichier .db, classe AsyncTask
Bonjour,
J'essaye de récupérer un fichier .db sur un serveur web, en le téléchargeant puis l'utiliser comme base de donnée locale. L'idée est de récupérer une base de donnée Web pour l'utiliser en local sans connexion internet.
J'ai déjà réussi, grâce à l'aide d'un membre du forum, à convertir la base de donnée. Le fichier généré est correct, il contient bien mes données.
Après plusieurs essais et corrections du code , j'ai donc découvert qu'il fallait absolument télécharger depuis une AsyncTask. Je me suis donc lancé dans une classe DownloadHelper qui hérite de AsyncTask.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| public final class DownloadHelper extends AsyncTask
{
protected void onPreExecute(Context context)
{
downloadDatabase(context);
}
protected Object doInBackground(Object... arg0)
{
copyServerDatabase(null);
return null;
}
private static boolean downloadDatabase(Context context)
{
try {
URL url = new URL("urldusite" + "basesqlite.db");
/* Open a connection to that URL. */
URLConnection ucon = url.openConnection();
/*
* Define InputStreams to read from the URLConnection.
*/
InputStream is = ucon.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
/*
* Read bytes to the Buffer until there is nothing more to read(-1).
*/
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int current = 0;
while ((current = bis.read()) != -1) {
baf.append((byte) current);
}
/* Convert the Bytes read to a String. */
FileOutputStream fos = null;
// Select storage location
fos = context.openFileOutput("basesqlite.db", Context.MODE_PRIVATE);
fos.write(baf.toByteArray());
fos.close();
Log.d("BTC", "downloaded");
}
catch (IOException e)
{
Log.e("BTC", "downloadDatabase Error: " , e);
return false;
}
catch (NullPointerException e)
{
Log.e("BTC", "downloadDatabase Error: " , e);
return false;
}
catch (Exception e)
{
Log.e("BTC", "downloadDatabase Error: " , e);
return false;
}
return true;
}
@SuppressLint("SdCardPath")
private void copyServerDatabase(Context context)
{
BtcDb db = new BtcDb(context,"clean.db",null,0);
// by calling this line an empty database will be created into the default system path
// of this app - we will then overwrite this with the database from the server
db.getReadableDatabase();
db.close();
OutputStream os = null;
InputStream is = null;
try {
// Log.d("BTC", "Copying DB from server version into app");
is = context.openFileInput("basesqlite.db");
os = new FileOutputStream("/data/data/com.example.btc_pe/databases/");
copyFile(os, is);
}
catch (Exception e)
{
Log.e("BTC", "Server Database was not found - did it download correctly?", e);
}
finally
{
try
{
//Close the streams
if(os != null)
{
os.close();
}
if(is != null)
{
is.close();
}
}
catch (IOException e)
{
Log.e("BTC", "failed to close databases");
}
}
Log.d("BTC", "Done Copying DB from server");
}
private static void copyFile(OutputStream os, InputStream is) throws IOException
{
byte[] buffer = new byte[1024];
int length;
while((length = is.read(buffer))>0)
{
os.write(buffer, 0, length);
}
os.flush();
}
} |
L'idée, telle que je la conçois, est de télécharger d'abord le fichier dans un évènement, puis le déplacer ensuite dans un second évènement. (J'ai hésité à faire les 2 dans le DoInBackground, mais j'ai peur qu'il tente de déplacer avant même qu'il n'ait fini de télécharger)
Pour l'anecdote, le fichier .db fait moins de 25Ko.
Je fais face à plusieurs soucis :
-AsyncTask me demande obligatoirement d'avoir "protected Object doInBackground(Object... arg0)", sauf que j'ai besoin du context de l'activité dans copyServerDatabase. Si je modifie les arguments de l'évènement, j'me prends une erreur. Comment je peux contourner le problème ?
-Je ne suis pas tout à fait sur de mon raisonnement sur l'exécution de tout le processus, j'aimerais l'avis de personnes plus expérimentées dans le domaine. Je pense pas faire une tache si peu courante que ça...
-Pour gérer un téléchargement, y'a pas une solution plus simple que tout manipuler d'une manière aussi bas niveau ? J'imagine que ça doit être assez courant quand même de devoir télécharger un fichier.
-Pour générer le fichier .db, je dois appeler un script php sur le serveur Web. Y'a une méthode assez simple et courte pour simplement envoyer une requête HTTP toute bête depuis Android ?
Merci d'avance.