videos tengo subir reproducir porque ocupan ocupa nube nada movil memoria llena liberar las interno interna google fotos espacio desde conversaciones como celular borrar almacenamiento android google-drive-sdk google-drive-api google-drive-android-api

android - tengo - Cómo evitar cargar siempre datos de aplicaciones en caché desde Google Drive



porque mi celular dice memoria llena si no tengo nada (1)

  1. La búsqueda en Google Drive es lenta. ¿Por qué no usar las propiedades de la carpeta base para almacenar la identificación del archivo zip? https://developers.google.com/drive/v2/web/properties
  2. Los nombres de archivo en Google Drive no son únicos, puede cargar varios archivos con los mismos nombres. El ID de archivo devuelto por Google, sin embargo, es único.

Actualmente, estoy usando la API de Android de Google Drive , para almacenar los datos de mi aplicación de Android, en la carpeta de aplicaciones de Google Drive .

Esto es lo que estoy haciendo al guardar los datos de mi aplicación

  1. Genere una suma de verificación para el archivo zip local actual.
  2. Busque en la Carpeta de la aplicación Google Drive para ver si hay un archivo zip de la Carpeta de la aplicación existente.
  3. Si es así, sobrescriba el contenido del archivo zip existente de la carpeta de aplicaciones, con los archivos zip locales actuales. Además, cambiaremos el nombre del nombre del archivo zip de la carpeta de aplicaciones existente, con la última suma de comprobación.
  4. Si no hay un archivo zip de la Carpeta de la Aplicación, genere un nuevo archivo zip de la Carpeta de la Aplicación, con el contenido del archivo zip local. Utilizaremos la última suma de comprobación como nombre de archivo zip de la carpeta de aplicaciones.

Aquí está el código que realiza las operaciones mencionadas anteriormente.

Genere un nuevo archivo zip de la carpeta de aplicaciones o actualice el archivo zip de la carpeta de aplicaciones existente

public static boolean saveToGoogleDrive(GoogleApiClient googleApiClient, File file, HandleStatusable h, PublishProgressable p) { // Should we new or replace? GoogleCloudFile googleCloudFile = searchFromGoogleDrive(googleApiClient, h, p); try { p.publishProgress(JStockApplication.instance().getString(R.string.uploading)); final long checksum = org.yccheok.jstock.gui.Utils.getChecksum(file); final long date = new Date().getTime(); final int version = org.yccheok.jstock.gui.Utils.getCloudFileVersionID(); final String title = getGoogleDriveTitle(checksum, date, version); DriveContents driveContents; DriveFile driveFile = null; if (googleCloudFile == null) { DriveApi.DriveContentsResult driveContentsResult = Drive.DriveApi.newDriveContents(googleApiClient).await(); if (driveContentsResult == null) { return false; } Status status = driveContentsResult.getStatus(); if (!status.isSuccess()) { h.handleStatus(status); return false; } driveContents = driveContentsResult.getDriveContents(); } else { driveFile = googleCloudFile.metadata.getDriveId().asDriveFile(); DriveApi.DriveContentsResult driveContentsResult = driveFile.open(googleApiClient, DriveFile.MODE_WRITE_ONLY, null).await(); if (driveContentsResult == null) { return false; } Status status = driveContentsResult.getStatus(); if (!status.isSuccess()) { h.handleStatus(status); return false; } driveContents = driveContentsResult.getDriveContents(); } OutputStream outputStream = driveContents.getOutputStream(); InputStream inputStream = null; byte[] buf = new byte[8192]; try { inputStream = new FileInputStream(file); int c; while ((c = inputStream.read(buf, 0, buf.length)) > 0) { outputStream.write(buf, 0, c); } } catch (IOException e) { Log.e(TAG, "", e); return false; } finally { org.yccheok.jstock.file.Utils.close(outputStream); org.yccheok.jstock.file.Utils.close(inputStream); } if (googleCloudFile == null) { // Create the metadata for the new file including title and MIME // type. MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder() .setTitle(title) .setMimeType("application/zip").build(); DriveFolder driveFolder = Drive.DriveApi.getAppFolder(googleApiClient); DriveFolder.DriveFileResult driveFileResult = driveFolder.createFile(googleApiClient, metadataChangeSet, driveContents).await(); if (driveFileResult == null) { return false; } Status status = driveFileResult.getStatus(); if (!status.isSuccess()) { h.handleStatus(status); return false; } } else { MetadataChangeSet metadataChangeSet = new MetadataChangeSet.Builder() .setTitle(title).build(); DriveResource.MetadataResult metadataResult = driveFile.updateMetadata(googleApiClient, metadataChangeSet).await(); Status status = metadataResult.getStatus(); if (!status.isSuccess()) { h.handleStatus(status); return false; } } Status status; try { status = driveContents.commit(googleApiClient, null).await(); } catch (java.lang.IllegalStateException e) { // java.lang.IllegalStateException: DriveContents already closed. Log.e(TAG, "", e); return false; } if (!status.isSuccess()) { h.handleStatus(status); return false; } status = Drive.DriveApi.requestSync(googleApiClient).await(); if (!status.isSuccess()) { // Sync request rate limit exceeded. // //h.handleStatus(status); //return false; } return true; } finally { if (googleCloudFile != null) { googleCloudFile.metadataBuffer.release(); } } }

Busque el archivo zip de la carpeta de aplicaciones existente

private static String getGoogleDriveTitle(long checksum, long date, int version) { return "jstock-" + org.yccheok.jstock.gui.Utils.getJStockUUID() + "-checksum=" + checksum + "-date=" + date + "-version=" + version + ".zip"; } // https://stackoverflow.com/questions/1360113/is-java-regex-thread-safe private static final Pattern googleDocTitlePattern = Pattern.compile("jstock-" + org.yccheok.jstock.gui.Utils.getJStockUUID() + "-checksum=([0-9]+)-date=([0-9]+)-version=([0-9]+)//.zip", Pattern.CASE_INSENSITIVE); private static GoogleCloudFile searchFromGoogleDrive(GoogleApiClient googleApiClient, HandleStatusable h, PublishProgressable p) { DriveFolder driveFolder = Drive.DriveApi.getAppFolder(googleApiClient); // https://stackoverflow.com/questions/34705929/filters-ownedbyme-doesnt-work-in-drive-api-for-android-but-works-correctly-i final String titleName = ("jstock-" + org.yccheok.jstock.gui.Utils.getJStockUUID() + "-checksum="); Query query = new Query.Builder() .addFilter(Filters.and( Filters.contains(SearchableField.TITLE, titleName), Filters.eq(SearchableField.TRASHED, false) )) .build(); DriveApi.MetadataBufferResult metadataBufferResult = driveFolder.queryChildren(googleApiClient, query).await(); if (metadataBufferResult == null) { return null; } Status status = metadataBufferResult.getStatus(); if (!status.isSuccess()) { h.handleStatus(status); return null; } MetadataBuffer metadataBuffer = null; boolean needToReleaseMetadataBuffer = true; try { metadataBuffer = metadataBufferResult.getMetadataBuffer(); if (metadataBuffer != null ) { long checksum = 0; long date = 0; int version = 0; Metadata metadata = null; for (Metadata md : metadataBuffer) { if (p.isCancelled()) { return null; } if (md == null || !md.isDataValid()) { continue; } final String title = md.getTitle(); // Retrieve checksum, date and version information from filename. final Matcher matcher = googleDocTitlePattern.matcher(title); String _checksum = null; String _date = null; String _version = null; if (matcher.find()){ if (matcher.groupCount() == 3) { _checksum = matcher.group(1); _date = matcher.group(2); _version = matcher.group(3); } } if (_checksum == null || _date == null || _version == null) { continue; } try { checksum = Long.parseLong(_checksum); date = Long.parseLong(_date); version = Integer.parseInt(_version); } catch (NumberFormatException ex) { Log.e(TAG, "", ex); continue; } metadata = md; break; } // for if (metadata != null) { // Caller will be responsible to release the resource. If release too early, // metadata will not readable. needToReleaseMetadataBuffer = false; return GoogleCloudFile.newInstance(metadataBuffer, metadata, checksum, date, version); } } // if } finally { if (needToReleaseMetadataBuffer) { if (metadataBuffer != null) { metadataBuffer.release(); } } } return null; }

El problema ocurre durante la carga de datos de la aplicación. Imagine las siguientes operaciones

  1. Suba datos zip a la carpeta de la aplicación Google Drive por primera vez. La suma de verificación es 12345 . El nombre de archivo que se usa es ...checksum=12345...zip
  2. Busque datos zip desde la carpeta de la aplicación Google Drive . Capaz de encontrar el archivo con nombre de archivo ...checksum=12345...zip . Descargue el contenido. Verifique que la suma de comprobación del contenido también sea 12345 .
  3. Sobrescriba los nuevos datos zip en el archivo existente de la carpeta de la aplicación Google Drive . La nueva suma de comprobación de datos zip es 67890 . Se cambia el nombre del archivo zip de la carpeta de la aplicación existente a ...checksum=67890...zip
  4. Busque datos zip desde la carpeta de la aplicación Google Drive . Capaz de encontrar el archivo con nombre de archivo ...checksum=67890...zip . Sin embargo, después de descargar el contenido, la suma de comprobación del contenido sigue siendo 12345 .

Descargar el archivo zip de la carpeta de aplicaciones

public static CloudFile loadFromGoogleDrive(GoogleApiClient googleApiClient, HandleStatusable h, PublishProgressable p) { final java.io.File directory = JStockApplication.instance().getExternalCacheDir(); if (directory == null) { org.yccheok.jstock.gui.Utils.showLongToast(R.string.unable_to_access_external_storage); return null; } Status status = Drive.DriveApi.requestSync(googleApiClient).await(); if (!status.isSuccess()) { // Sync request rate limit exceeded. // //h.handleStatus(status); //return null; } GoogleCloudFile googleCloudFile = searchFromGoogleDrive(googleApiClient, h, p); if (googleCloudFile == null) { return null; } try { DriveFile driveFile = googleCloudFile.metadata.getDriveId().asDriveFile(); DriveApi.DriveContentsResult driveContentsResult = driveFile.open(googleApiClient, DriveFile.MODE_READ_ONLY, null).await(); if (driveContentsResult == null) { return null; } status = driveContentsResult.getStatus(); if (!status.isSuccess()) { h.handleStatus(status); return null; } final long checksum = googleCloudFile.checksum; final long date = googleCloudFile.date; final int version = googleCloudFile.version; p.publishProgress(JStockApplication.instance().getString(R.string.downloading)); final DriveContents driveContents = driveContentsResult.getDriveContents(); InputStream inputStream = null; java.io.File outputFile = null; OutputStream outputStream = null; try { inputStream = driveContents.getInputStream(); outputFile = java.io.File.createTempFile(org.yccheok.jstock.gui.Utils.getJStockUUID(), ".zip", directory); outputFile.deleteOnExit(); outputStream = new FileOutputStream(outputFile); int read = 0; byte[] bytes = new byte[1024]; while ((read = inputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, read); } } catch (IOException ex) { Log.e(TAG, "", ex); } finally { org.yccheok.jstock.file.Utils.close(outputStream); org.yccheok.jstock.file.Utils.close(inputStream); driveContents.discard(googleApiClient); } if (outputFile == null) { return null; } return CloudFile.newInstance(outputFile, checksum, date, version); } finally { googleCloudFile.metadataBuffer.release(); } }

Primero pensé

Status status = Drive.DriveApi.requestSync(googleApiClient).await()

no hace bien el trabajo. Falla en la mayoría de las situaciones, con el mensaje de error Se Sync request rate limit exceeded. De hecho, el límite requestSync impuesto en requestSync hace que la API no sea particularmente útil - Android Google Play / Drive Api

Sin embargo, incluso cuando requestSync loadFromGoogleDrive , loadFromGoogleDrive solo puede obtener el último nombre de archivo, pero el contenido de la suma de verificación está desactualizado.

Estoy 100% seguro de que loadFromGoogleDrive me devuelve un contenido de datos en caché, con las siguientes observaciones.

  1. driveFile.open un DownloadProgressListener en driveFile.open , bytesDownloaded es 0 y bytesExpected es -1.
  2. Si uso la API de Google Drive Rest , con el siguiente código de escritorio , puedo encontrar el último nombre de archivo con el contenido de suma de verificación correcto.
  3. Si desinstalo mi aplicación de Android y la reinstalo nuevamente, loadFromGoogleDrive podrá obtener el último nombre de archivo con el contenido de suma de verificación correcto.

¿Hay alguna forma sólida de evitar cargar siempre los datos de la aplicación en caché de Google Drive?

Me las arreglo para producir una demostración. Estos son los pasos para reproducir este problema.

Paso 1: descargue el código fuente

https://github.com/yccheok/google-drive-bug

Paso 2: configuración en la consola API

Paso 3: Presione el botón GUARDAR "123.TXT" CON CONTENIDO "123"

Se creará un archivo con el nombre de archivo "123.TXT", contenido "123" en la carpeta de la aplicación.

Paso 4: Presione el botón GUARDAR "456.TXT" CON CONTENIDO "456"

El archivo anterior cambiará de nombre a "456.TXT", con el contenido actualizado a "456"

Paso 5: Presione el botón CARGAR EL ÚLTIMO ARCHIVO GUARDADO

Se encontró un archivo con el nombre de archivo "456.TXT", pero se lee el contenido en caché anterior "123". Esperaba contenido "456".

Tenga en cuenta que, si

  1. Desinstalar la aplicación de demostración.
  2. Vuelva a instalar la aplicación de demostración.
  3. Presione el botón CARGAR EL ÚLTIMO ARCHIVO GUARDADO, se encuentra el archivo con el nombre de archivo "456.TXT" y el contenido "456".

Había presentado un informe de problemas oficialmente: https://code.google.com/a/google.com/p/apps-api-issues/issues/detail?id=4727

Otra información

Así es como se ve debajo de mi dispositivo: http://youtu.be/kuIHoi4A1c0

Me doy cuenta de que no todos los usuarios tendrán este problema. Por ejemplo, lo había probado con otro Nexus 6, Google Play Services 9.4.52 (440-127739847). El problema no aparece.

Había compilado un APK para probarlo: https://github.com/yccheok/google-drive-bug/releases/download/1.0/demo.apk