¿Cómo medir el tamaño de los datos de las aplicaciones de Android e identificar las fugas de almacenamiento?

Hice una pequeña aplicación de Android y la he estado utilizando desde hace tiempo. Me di cuenta de que, en los ajustes, en la línea "datos" de las características de mi aplicación (no estoy interesado en analizar la cantidad mostrada en la línea "aplicación" ni en la línea "caché"), muestra unos 20 MB, que Me parecía mucho. Me temo que la aplicación tiene fugas de almacenamiento (es decir, que produce datos que nunca se borran).

Decidí investigar y medir lo que podría tomar ese espacio. Utilizo prácticamente todas las opciones de almacenamiento disponibles para esta aplicación: DB de SQLite, archivos internos, archivos externos, preferencias compartidas (y archivos de caché incluyendo la carga de imágenes Glide ).

Hasta ahora, gracias a una pregunta en SQLite DB , encontré que mi archivo de base de datos toma alrededor de 500 kB. Encontré explorando recursivamente los archivos y carpetas de la carpeta getFilesDir() que utilizo 10 kB de datos en archivos externos internos y externos a la aplicación. Todavía no he analizado el tamaño de las preferencias compartidas, pero almaceno menos de 20 pares clave / valor.

Explorando la carpeta getCacheDirs() También encontré que Glide usa aproximadamente 3 MB de caché (cerca de lo que dice la aplicación de configuración de Android).

Mi pregunta es, ¿qué pistas me he perdido para encontrar donde este 19,5 MB de datos no puedo localizar? ¿He olvidado algún tipo de almacenamiento que podría tomar espacio? Y, más generalmente, ¿hay herramientas para analizar las fugas de almacenamiento (es decir, los datos producidos por la aplicación que nunca podrían borrarse)?

No hay fugas de almacenamiento.

No contó el odex (dalvik) o oat (android runtime). Normalmente se encuentran en

 /data/dalvik-cache/xxx.odex /data/dalvik-cache/<target-architecture>/xxx.oat 

Estos archivos son generados por el sistema para la optimización durante el tiempo de instalación.

También no contó su archivo APK en el que se encuentra en

 /data/app/xxx.yyy.zzz.apk 

Los directorios o archivos no son accesibles desde adb shell si el dispositivo no está enraizado.

Creo que la demostración del uso del almacenaje en los ajustes incluye las tres partes siguientes

 /data/data/xxx.yyy.zzz /data/app/xxx.yyy.zzz.apk odex or oat file 

Por lo tanto, el tamaño de almacenamiento que contó bajo /data/data/xxx.yyy.zzz siempre es menor que el tamaño total de la configuración.

Puede utilizar MAT TOOL para optimizar los problemas de memoria / tamaño en su aplicación. Visualiza qué parte de su aplicación utiliza más memoria.

Ejecutar su aplicación en Android-studio y vaya a Herramientas-> Android-> AndroidDeviceMonitor , ejecute su escenario y en el monitor del dispositivo haga clic para descargar su archivo .hprof app siga la imagen que adjunto a continuación Descargar archivo .hprof

Después de que usted necesita convertir el archivo .hprof de Android-estudio a Eclipse Mat apoyó el archivo .hprof usando hprof-conv.exe dentro sdk-> plataforma-herramientas y siga el cmd en su promt CMD

 F:\Android_Studio_SDK\platform-tools>hprof-conv "C:\Users\Bala\Desktop\your_AS_file.hprof" "C:\Users\Bala\Desktop\MAT_File_Name.hprof" 

Y en MAT Tool vaya a File -> OpenHeapDump para abrir su archivo .hprof, mostrará su memoria de aplicación utilizar por paquete, clase, objeto .. etc;

Algunos enlaces de referencia para aprender sobre MAT Tool
Enlace 1
Enlace 2

Después de la sugerencia de @James, empecé a explorar las diferentes carpetas, y después de discutir el problema con un colega y tratando de explorar muchas carpetas, finalmente encontré que la mayoría de los datos procedían de la caché de un antiguo Webview que tenía. Estoy publicando toda mi investigación, espero que ayude.

analyseStorage(this) el siguiente código cuando se inicia la aplicación, llamando a analyseStorage(this) de mi actividad principal:

 public void analyseStorage(Context context) { long totalSize = 0; File appBaseFolder = context.getFilesDir().getParentFile(); for (File f: appBaseFolder.listFiles()) { if (f.isDirectory()) { long dirSize = browseFiles(f); totalSize += dirSize; Log.d(STORAGE_TAG, f.getPath() + " uses " + dirSize + " bytes"); } else { totalSize += f.length(); } } Log.d(STORAGE_TAG, "App uses " + totalSize + " total bytes"); } private long browseFiles(File dir) { long dirSize = 0; for (File f: dir.listFiles()) { dirSize += f.length(); //Log.d(STORAGE_TAG, dir.getAbsolutePath() + "/" + f.getName() + " weighs " + f.length()); if (f.isDirectory()) { dirSize += browseFiles(f); } } return dirSize; } 

Lo importante es escanear específicamente context.getFilesDir().getParentFile() que coincide con la carpeta /data/data/my.app.package/

Después de ejecutar ese código, tenía los siguientes registros:

 D/storage﹕ /data/data/my.app.package/lib uses 0 bytes D/storage﹕ /data/data/my.app.package/cache uses 3371773 bytes D/storage﹕ /data/data/my.app.package/databases uses 483960 bytes D/storage﹕ /data/data/my.app.package/shared_prefs uses 604 bytes D/storage﹕ /data/data/my.app.package/app_webview uses 9139469 bytes D/storage﹕ /data/data/my.app.package/files uses 7723 bytes D/storage﹕ /data/data/my.app.package/app_ACRA-approved uses 0 bytes D/storage﹕ /data/data/my.app.package/app_ACRA-unapproved uses 0 bytes D/storage﹕ App uses 13003529 total bytes 

Lo que pude ver es:

  • La memoria caché, utilizada sólo por Glide para la carga de imágenes, toma 3 MB
  • La base de datos SQLite toma 500kB
  • Las preferencias compartidas toman 600B
  • La caché para todas las vistas de Web que solía tener aún toma 9 MB
  • El resto de los archivos, bajo files y otras carpetas, es utilizado principalmente por ACRA para el seguimiento de errores y tomar 10kB

Al final, finalmente descubrí que la mayoría de mis datos fueron a la caché de Webview, en realidad no se almacenó explícitamente como caché. He eliminado estos archivos y en realidad redujo el tamaño de mi aplicación en 20 MB, incluso más de lo indicado anteriormente. Ahora sé qué orden de magnitud tomo los datos de mi aplicación.

Puede utilizar una biblioteca como Leak Canary para detectar automáticamente todas las pérdidas de memoria dentro de su aplicación: https://corner.squareup.com/2015/05/leak-canary.html

También puede ir al DDMS en Android Studio y obtener más información del almacenamiento en su aplicación sin codificar nada. Sin embargo, la mayoría de las fugas serían detectadas por Leak Canary.

¡Espero eso ayude!

  • SQLiteOpenHelper no puede llamar a onCreate?
  • ¿Por qué algunos métodos SQLite esperan argumentos como un objeto , mientras que otros necesitan una cadena ?
  • Entender el campo de incremento automático de Android de sqlite
  • Conversión de String en DateTime: Android
  • Demasiados argumentos de enlace. 5 argumentos fueron proporcionados, pero la declaración necesita 4 argumentos
  • Cómo abrir / cerrar SQLite db en Android correctamente
  • ¿Cómo implementar deshacer un solo paso para los cambios en la base de datos SQLite?
  • Cómo eliminar la base de datos SQLite de Android mediante programación
  • Random () en sqlite y Android sdk
  • SQLite para la vista de tabla personalizada de Android (vista de SQL, no vista de Android) discrepancia?
  • Sigue recibiendo NullPointerExceptions al intentar llamar a getWritableDatabase ()
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.