Ionic - Android Marshmallow y File Transfer

  • por Nicolás Cofré

Un recurso que sin duda algún día necesitaremos usar en Ionic es el acceso al almacenamiento, tanto para descargar, como para subir archivos. Una forma muy sencilla de hacer estas acciones es con el plugin de cordova "cordova-plugin-file-transfer", el cual mediante unas pocas lineas podemos realizar lo ya nombrado, pero lamentablemente con las últimas actualizaciones de Android esto ha cambiado.

Con la llegada de Android Marshmallow (6.0, API Level 23) muchas cosas mejoraron y cambiaron, una de ellas es la forma de conceder los permisos, como por ejemplo: acceso al Micrófono, Cámara, Ubicación, Almacenamientos, entre otros. Estos permisos se han calificados en "Permisos normales" y "Permisos peligrosos".

  • Los permisos normales no amenazan directamente la privacidad del usuario. Si una aplicación requiere un permiso normal, el sistema concede el permiso automáticamente.
  • Los permisos peligrosos solicitan acceso a los datos confidenciales del usuario. Si una aplicación requiere un permiso peligroso, el usuario debe darle la aprobación explícita a la aplicación.

A continuación haremos un ejemplo de como descargar una imagen en Ionic.

El acceso al almacenamiento del usuario se considera un permiso peligroso, por ende debemos solicitar los permisos necesarios en el momentos que se necesita acceder. Una forma de solicitar los permisos al momentos de requerirlo es implementar el plugin "cordova-plugin-android-permission".

1.- En nuestra aplicación agregaremos los plugins necesarios (package.json) e instalamos:

  • package.json
"cordova-plugin-file",
"cordova-plugin-file-transfer",
"cordova-plugin-android-permissions"
  • Instalación
cordova plugin add cordova-plugin-file
cordova plugin add cordova-plugin-file-transfer
cordova plugin add cordova-plugin-android-permissions

o

ionic state restore

2.- Creamos el método "download" el cual realiza la descarga del archivo.

function download() {
    // URL Imagen para descargar
    var url = "http://i.imgur.com/SmXu3j7.jpg";
    // Nombre del archivo
    var filename = url.split("/").pop();
    // Ruta donde se guardará
    var targetPath = cordova.file.externalRootDirectory + 'Download/' + filename;

    // Instancia del plugin FileTransfer
    var fileTransfer = new FileTransfer();
    var uri = encodeURI(url);
    var trustHosts = true
    var options = {};

    // Método que realiza la descarga
    fileTransfer.download(
      uri,
      targetPath,
      function (entry) {
      	// Success
        alert("download complete: " + entry.toURL());
      },
      function (error) {
      	// Error
        alert("download error source " + error.source);
        alert("download error target " + error.target);
        alert("download error code" + error.code);
      },
      trustHosts,
      options
      );
    }

})

3.- Creamos la variable "permissions" en nuestro controlador.

var permissions;

4.- Agregamos la función "checkPermissionCallback" la cual se encarga de solicitar los permisos al usuario y valida si fueron concedidos los permisos o no para continuar con la descarga.

function checkPermissionCallback(status) {
    // Consulta si ya tiene permisos
    if (!status.hasPermission) {
      var errorCallback = function () {
        alert('Permisos denegados');
      }
      permissions.requestPermission(
        permissions.READ_EXTERNAL_STORAGE,
        function (status) {
          if (!status.hasPermission) {
            errorCallback();
          } else {
                // Ejecuta la función si se dieron permisos
                download();
              }
            },
            errorCallback);
    } else {
      download();
    }
  }

5.- Agregamos un botón a la vista y le asociamos una función (en este caso "downloadFile") la cual ejecuta a "checkPermissionCallback" para realizar la descarga.

$scope.downloadFile = downloadFile;

function downloadFile() {
	// A permissions le asignamos el plugin de cordova
	permissions = cordova.plugins.permissions;
	// Ejecuta la función checkPermissionCallback
	permissions.hasPermission(permissions.READ_EXTERNAL_STORAGE, checkPermissionCallback, null);
}

Y listo!, ya podemos ver la imagen guardada en nuestro dispositivo. Si volvemos a presionar sobre el botón y ya le concedimos los permisos, no volverá a pedirlos.

Para más información:

 

Referencias:

Éxito!