Adaptar a api 30, visor de archivo

38 views
Skip to first unread message

Jaume Tugores

unread,
Jun 19, 2021, 6:39:54 AM6/19/21
to desarrolladores-android
Estoy adaptando la app a la api 30, descargo un fichero gpx desde una página y lo guardo en las carpetas particulares de la app, luego hago una copia a la carpeta download para que el visor puede acceder a el, arranco la activity de la siguiente manera:

    //-Carga el fichero gpx creado en la sd Downloads
    void visor_gpx(String pGpx) {
        String ruta = Environment.getExternalStorageDirectory() + File.separator + Environment.DIRECTORY_DOWNLOADS;
        File miGpx = new File(ruta, pGpx);
        if (miGpx.exists()) {
            Uri gpxfURI = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".fileprovider", miGpx);
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(gpxfURI, "text/xml");
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            try {
                startActivity(intent);
            } catch (Exception e) {
                Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        }
    }


la activity arranca pero me da un aviso de que hay error intentando acceder al fichero gpx "miGpx" y en el try, no salta ningún error.
podrian decirme como hacerlo para que el visor_gpx pueda leer el fichero. Si el fichero lo abro desde el explorador de archivos se abre en el mismo visor correctamente. 

Gabriel Pozo

unread,
Jun 20, 2021, 8:10:44 AM6/20/21
to desarrollad...@googlegroups.com
Y en el log, que te muestra cuando realizas esa acción?
Las URI que armas ahí están correctas?

--
Para participar es necesario que leas detenidamente las normas del grupo: https://goo.gl/xeTRQm
---
Has recibido este mensaje porque estás suscrito al grupo "desarrolladores-android" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a desarrolladores-a...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/desarrolladores-android/dc4fe570-247e-4be9-a708-e5a30bfd5044n%40googlegroups.com.

Jaume Tugores

unread,
Jun 21, 2021, 4:35:47 AM6/21/21
to desarrolladores-android
Ni el try da error  ni el log escribe una sola linea al ejecutar:
try {
    startActivity(intent);
} catch (Exception e) {
  Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
La app del visor arranca correctamente pero no puede abrir el fichero gpx que le paso en la linea:
Uri gpxfURI = FileProvider.getUriForFile(this, this.getApplicationContext().getPackageName() + ".fileprovider", miGpx);
el fichero se ve en el debug que está correcto, lo detecta en la linea:
 if (miGpx.exists()) {

Si en el manifiest pongo:
android:requestLegacyExternalStorage="true"
funciona correctamente, es decir lo carga y se puede ver en el visor.

Gabriel Pozo

unread,
Jun 21, 2021, 9:10:42 AM6/21/21
to desarrollad...@googlegroups.com
Ahhh puede ser para la compatibilidad con la forma de almacenamiento con Android 11
Yo usaría ese flag en el manifest,  sino busca de esos métodos los deprecated y vas a tener que cambiar el código. Para usar los "nuevos"


Jaume Tugores

unread,
Jun 22, 2021, 12:45:02 AM6/22/21
to desarrolladores-android
Si, es lo que hago, pero quería adaptar el código a la nueva compatibilidad y no se como hacerlo.
Gracias.

Gabriel Pozo

unread,
Jun 22, 2021, 9:43:15 AM6/22/21
to desarrollad...@googlegroups.com
Entonces deberías ver esto:

Y de acuerdo a lo que necesites, ver si vas a usar el almacenamiento compartido:
O al almacenamiento espesífico:

Te recomiendo ver este video: https://www.youtube.com/watch?v=RjyYCUW-9tY
Y este blog, quizás también te pueda ayudar.

Saludos, Gabriel


Jaume Tugores

unread,
Jun 26, 2021, 12:18:03 AM6/26/21
to desarrolladores-android
Bueno, al fin lo he encontrado, pongo aqui la solución por si puede servir a alguien:

El intent para que el visor de gpx pueda abrir el fichero previamente puesto en la carpeta compartida download no cambia, es el mismo:

    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(uriGpx,"text/xml");
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
    startActivity(intent);
Lo que si cambia es la manera de pasarle la uri del fichero gpx, hay que pasarle la uri a traves de MediaStore, es una uri como esta:
content://media/external/downloads/9815
En mi caso, lo que hago es a traves de una coxexión a mi servidor descargar el fichero gpx y colocarlo en una ubicadion privada (de la app) y luego copiarlo a la carpeta compartida donwload usando MediaStore, al hacerlo asi la funciòn de copiado ya devuelve la uri al archivo que es  la que se pasa al intent.
Pongo aquí la función de copiado usando MediaStore:

    //-Copia un archivo de una ubicación privada a donwload pública
    public Uri copyFileD(File forg, String filename) {
        Boolean ok;
        InputStream is = null;
        OutputStream os = null;
        Uri target;
        Uri uri;
        ContentResolver cr = nContexto.getContentResolver();
        ContentValues values = new ContentValues();
        values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DOWNLOADS);
        values.put(MediaStore.MediaColumns.IS_PENDING, true);
        values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename);
        if (Build.VERSION.SDK_INT >= 29) {
            target = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
        } else {
            target = MediaStore.Files.getContentUri("external");
        }
        cr.delete(target, null, null); //-borra todos los archivos puesto en download por esta app, deja intactos el resto.
        uri = cr.insert(target, values);
        if (uri == null) {
            ok = false;
        } else ok = true;
        if (ok) {
            try {
                is = new FileInputStream(forg);
                os = cr.openOutputStream(uri, "rw");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                ok = false;
            }
            byte[] b = new byte[8192];
            try {
                for (int r; (r = is.read(b)) != -1; ) {
                    try {
                        os.write(b, 0, r);
                    } catch (IOException e) {
                        e.printStackTrace();
                        ok = false;
                    }
                }
                os.flush();
                os.close();
                is.close();
            } catch (Throwable tr) {
                tr.printStackTrace();
                ok = false;
            }
            if (Build.VERSION.SDK_INT >= 29) {
                values = new ContentValues();
                values.put(MediaStore.MediaColumns.IS_PENDING, false);
                cr.update(uri, values, null, null);
            }
        }
        return uri;  //-es la uri necesaria para pasar al intent
    }

* Así es como lo tengo y de momento funciona.

Gabriel Pozo

unread,
Jun 26, 2021, 7:49:43 AM6/26/21
to desarrollad...@googlegroups.com
Que bueno que encontraste la solución

Saludos, Gabriel


Reply all
Reply to author
Forward
0 new messages