Descargar la base de datos SQLite desde Internet y cargarla en la aplicación de Android

Para mi aplicación de Android, me gustaría usar una gran base de datos (unos 45 MB).

Una solución sería incluir la base de datos (dividida) en la carpeta de activos y copiarla al directorio de la base de datos en la primera puesta en marcha.

Pero esto consumiría espacio en disco dos veces: una vez en la carpeta de activos donde el archivo no se puede eliminar y una vez en el directorio de la base de datos donde se ha copiado.

Así que prefiero descargar la base de datos de Internet (servidor web) en la primera puesta en marcha. ¿Cómo podría hacer esto? ¿Puedo descargar un archivo SQLite completo y guardarlo en el directorio de la base de datos? ¿O debo ir con archivos de datos JSON que se utilizan para rellenar la base de datos?

Una solución sería incluir la base de datos (dividida) en la carpeta de activos y copiarla al directorio de la base de datos en la primera puesta en marcha.

No tendría que ser dividido, sólo ZIPped. Consulte SQLiteAssetHelper para obtener un ejemplo.

¿Cómo podría hacer esto?

Utilice HttpUrlConnection . O bien, utilice HttpClient .

¿Puedo descargar un archivo SQLite completo y guardarlo en el directorio de la base de datos?

Sí. Utilice getDatabasePath() para obtener la ruta local correcta para utilizar.

¿O debo ir con archivos de datos JSON que se utilizan para rellenar la base de datos?

Podrías, pero por 45 MB, eso sería horriblemente lento.

Habiendo sido preguntado qué solución terminé con, aquí está el código que utilicé (aproximadamente). Puede que no esté completo, y tampoco es elegante ni limpio. Pero tal vez puede ser de ayuda para usted.

MyActivity.java

 public class MyActivity extends Activity { private static final String SD_CARD_FOLDER = "MyApp"; private static final String DB_DOWNLOAD_PATH = "http://www.example.org/downloads/dictionary.sqlite"; private Database mDB = null; private DatabaseDownloadTask mDatabaseDownloadTask = null; private DatabaseOpenTask mDatabaseOpenTask = null; private class DatabaseDownloadTask extends AsyncTask<Context, Integer, Boolean> { @Override protected void onPreExecute() { mProgressDialog = new ProgressDialog(MyActivity.this); mProgressDialog.setTitle(getString(R.string.please_wait)); mProgressDialog.setMessage(getString(R.string.downloading_database)); mProgressDialog.setIndeterminate(false); mProgressDialog.setMax(100); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); mProgressDialog.setCancelable(false); mProgressDialog.show(); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } @Override protected Boolean doInBackground(Context... params) { try { File dbDownloadPath = new File(Database.getDatabaseFolder()); if (!dbDownloadPath.exists()) { dbDownloadPath.mkdirs(); } HttpParams httpParameters = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(httpParameters, 5000); HttpConnectionParams.setSoTimeout(httpParameters, 5000); DefaultHttpClient client = new DefaultHttpClient(httpParameters); HttpGet httpGet = new HttpGet(DB_DOWNLOAD_PATH); InputStream content = null; try { HttpResponse execute = client.execute(httpGet); if (execute.getStatusLine().getStatusCode() != 200) { return null; } content = execute.getEntity().getContent(); long downloadSize = execute.getEntity().getContentLength(); FileOutputStream fos = new FileOutputStream(Database.getDatabaseFolder()+Database.DATABASE_NAME+".sqlite"); byte[] buffer = new byte[256]; int read; long downloadedAlready = 0; while ((read = content.read(buffer)) != -1) { fos.write(buffer, 0, read); downloadedAlready += read; publishProgress((int) (downloadedAlready*100/downloadSize)); } fos.flush(); fos.close(); content.close(); return true; } catch (Exception e) { if (content != null) { try { content.close(); } catch (IOException e1) {} } return false; } } catch (Exception e) { return false; } } protected void onProgressUpdate(Integer... values) { if (mProgressDialog != null) { if (mProgressDialog.isShowing()) { mProgressDialog.setProgress(values[0]); } } } @Override protected void onPostExecute(Boolean result) { if (mProgressDialog != null) { mProgressDialog.dismiss(); mProgressDialog = null; } if (result.equals(Boolean.TRUE)) { Toast.makeText(MyActivity.this, getString(R.string.database_download_success), Toast.LENGTH_LONG).show(); mDatabaseOpenTask = new DatabaseOpenTask(); mDatabaseOpenTask.execute(new Context[] { MyActivity.this }); } else { Toast.makeText(getApplicationContext(), getString(R.string.database_download_fail), Toast.LENGTH_LONG).show(); finish(); } } } private class DatabaseOpenTask extends AsyncTask<Context, Void, Database> { @Override protected Database doInBackground(Context ... ctx) { try { String externalBaseDir = Environment.getExternalStorageDirectory().getAbsolutePath(); // DELETE OLD DATABASE ANFANG File oldFolder = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+SD_CARD_FOLDER); File oldFile = new File(oldFolder, "dictionary.sqlite"); if (oldFile.exists()) { oldFile.delete(); } if (oldFolder.exists()) { oldFolder.delete(); } // DELETE OLD DATABASE ENDE File newDB = new File(Database.getDatabaseFolder()+"dictionary.sqlite"); if (newDB.exists()) { return new Database(ctx[0]); } else { return null; } } catch (Exception e) { return null; } } @Override protected void onPreExecute() { mProgressDialog = ProgressDialog.show(MainActivity.this, getString(R.string.please_wait), "Loading the database! This may take some time ...", true); } @Override protected void onPostExecute(Database newDB) { if (mProgressDialog != null) { mProgressDialog.dismiss(); mProgressDialog = null; } if (newDB == null) { mDB = null; AlertDialog.Builder downloadDatabase = new AlertDialog.Builder(MyActivity.this); downloadDatabase.setTitle(getString(R.string.downloadDatabase)); downloadDatabase.setCancelable(false); downloadDatabase.setMessage(getString(R.string.wantToDownloadDatabaseNow)); downloadDatabase.setPositiveButton(getString(R.string.download), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); mDatabaseDownloadTask = new DatabaseDownloadTask(); mDatabaseDownloadTask.execute(); } }); downloadDatabase.setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); finish(); } }); downloadDatabase.show(); } else { mDB = newDB; } } } @Override public void onDestroy() { super.onDestroy(); if (mDatabaseDownloadTask != null) { if (mDatabaseDownloadTask.getStatus() != AsyncTask.Status.FINISHED) { mDatabaseDownloadTask.cancel(true); } } if (mDatabaseOpenTask != null) { if (mDatabaseOpenTask.getStatus() != AsyncTask.Status.FINISHED) { mDatabaseOpenTask.cancel(true); } } if (mProgressDialog != null) { mProgressDialog.dismiss(); mProgressDialog = null; } if (mDB != null) { mDB.close(); mDB = null; } } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { Toast.makeText(getApplicationContext(), getString(R.string.sd_card_not_found), Toast.LENGTH_LONG).show(); finish(); } mDatabaseOpenTask = new DatabaseOpenTask(); mDatabaseOpenTask.execute(new Context[] { this }); } } 

Database.java

Public class La base de datos extiende SQLiteOpenHelper {

 private static final String DATABASE_NAME = "dictionary"; private String DATABASE_PATH = null; private static final int DATABASE_VERSION = 1; private static final String PACKAGE_NAME = "com.my.package"; private SQLiteDatabase db; public Database(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); DATABASE_PATH = getDatabaseFolder()+DATABASE_NAME+".sqlite"; db = getWritableDatabase(); } public static String getDatabaseFolder() { return Environment.getExternalStorageDirectory().getAbsolutePath()+"/Android/data/"+PACKAGE_NAME+"/databases/"; } @Override public synchronized SQLiteDatabase getWritableDatabase() { try { if (db != null) { if (db.isOpen()) { return db; } } return SQLiteDatabase.openDatabase(DATABASE_PATH, null, SQLiteDatabase.OPEN_READWRITE | SQLiteDatabase.NO_LOCALIZED_COLLATORS); } catch (Exception e) { return null; } } @Override public synchronized void close() { if (db != null) { db.close(); db = null; } super.close(); } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } 

}

Creo que el enfoque JSON sería una mejor idea si su base de datos es tan grande.

No estoy 100% seguro, pero creo que cuando publique una actualización de su aplicación, su dispositivo descargará toda la aplicación. Si está agrupando un archivo de 45mb con su aplicación, esto significaría que cada vez que empuje una actualización, sus usuarios se quedarán atascados con la descarga de un archivo de 45mb. No es Buena idea.

Lo que podría hacer es incluir la base de datos correctamente estructurada sin datos en su aplicación. Cuando el usuario abre la aplicación podría conectarse a su servidor web y obtener los datos JSON para rellenar la base de datos. De esta manera, cuando el usuario actualiza su aplicación, no se quedará atascado con la descarga de un nuevo archivo grande. Las actualizaciones no eliminan las bases de datos existentes.

Incluso podría imaginar cosas y obtener partes de la base de datos a través de JSON hasta que el usuario lo tenga todo. De esta manera si estás haciendo una consulta monstruo y pierden conexión a Internet nada malo pasará.

  • Intento escribir una base de datos readonly ... pero no estoy
  • ¿Cómo puedo obtener información sobre la columna causó restricción de clave externa en android sqlite?
  • Cómo escribir contiene consulta en SQLite fts3 fulltext search
  • Archivo está encriptado o no es una base de datos (excepción net.sqlcipher.database.SQLiteException)
  • Diferencia entre las funciones window.openDatabase () y window.sqlitePlugin.openDatabase ()?
  • ¿Por qué utilizar SQLiteOpenHelper sobre SQLiteDatabase?
  • Sqlite eliminar la sintaxis de consulta en Android
  • Aplicación detenida en Android / SQLITE ERROR /
  • Cómo seleccionar datos entre dos intervalos de fechas en android SQLite
  • GetWritableDatabase () VS getReadableDatabase ()
  • Eliminar filas sqllite de android de más de x días
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.