Nexus 4 no muestra archivos a través de MTP

80

Estoy intentando simplemente escribir un archivo XML simple en la tarjeta SD y me di cuenta de que mi Nexus 4 sí escribe el archivo, pero no se puede ver a través del protocolo MTP con Windows 7.

código:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    CustomerQueryRqType customerQueryRequest = new CustomerQueryRqType();
    Serializer serializer = new Persister();
    File myFile = new File(Environment.getExternalStorageDirectory() + "/customerQueryRequest.xml");

    try {
        boolean created = myFile.createNewFile();
        serializer.write(customerQueryRequest, myFile);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Puedo ver el archivo en el teléfono con Astro File Manager:

Captura de pantalla

pero Windows no lo ve ...:

Captura de pantalla

adb shell en el directorio muestra:

ls -l
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Alarms
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Android
drwxrwxr-x root     sdcard_rw          2012-11-21 19:30 DCIM
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Download
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Movies
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Music
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Notifications
drwxrwxr-x root     sdcard_rw          2012-11-19 12:06 Pictures
drwxrwxr-x root     sdcard_rw          1970-01-16 20:51 Podcasts
drwxrwxr-x root     sdcard_rw          2012-11-19 13:22 Ringtones
drwxrwxr-x root     sdcard_rw          2012-11-19 14:33 bluetooth
-rw-rw-r-- root     sdcard_rw       79 2012-12-05 22:26 customerQueryRequest.xml
drwxrwxr-x root     sdcard_rw          2012-11-20 02:50 data
-rw-rw-r-- root     sdcard_rw    11394 2012-11-19 13:54 eightpen_custom_gestures
drwxrwxr-x root     sdcard_rw          2012-11-19 13:17 media

¿Qué pasa con mi Nexus 4? ¿Por qué esconde mis cosas de Windows?

luz de la luna
fuente
1
Pensé que estaba haciendo algo mal. Ahora sé que no estoy solo.
neverMind9

Respuestas:

72

Parece ser un problema conocido que afecta el acceso a archivos USB de Android a través de MTP . La caché de MTP queda desactualizada hasta que se reinicia el teléfono.

Una solución alternativa es:

  • Borrar los datos de la aplicación "Almacenamiento multimedia"
  • Utilice la aplicación SDrescan o SD Scanner (también funciona en Android 4.4 / 5, disponible en F-Droid ) para forzar una actualización

O simplemente evite usar USB en absoluto. El problema no afecta a otros métodos de acceso a los archivos. Por ejemplo, pruebe AirDroid para transferir archivos.


Nota: Esto no funciona para Android 5.0.2: después de borrar "Almacenamiento de medios" y usar un reescáner SD, las carpetas aparecen en Windows 7 como archivos 4K que no se pueden abrir. La única solución en ese momento es borrar una vez más el almacenamiento de medios y reiniciar el dispositivo

Kevin Panko
fuente
2
Instale SDrescan, ejecútelo: ¡arreglado! Muchas gracias
PiTheNumber
Esto no estaba sucediendo antes, pero hoy sí. Por cierto, reinicio debería funcionar IDK por qué no está funcionando.
Muhammad Babar
Es extraño después de reiniciar el teléfono 3 veces, apareció.
Muhammad Babar
Esto no funciona para Android 5.0.2: después de borrar "Almacenamiento multimedia" y usar un reescáner SD, las carpetas aparecen en Windows 7 como archivos 4K que no se pueden abrir. La única solución en ese momento es borrar una vez más el Almacenamiento de medios y reiniciar el dispositivo.
Antonio
Esto tampoco funcionó en Nexus 7 Android 4.4.2. Mi Mac informa que mi directorio personalizado es un archivo de 4k.
Joe Lapp
44

Puede usar el siguiente código después de cerrar el archivo

MediaScannerConnection.scanFile(this, new String[] { file.getAbsolutePath() }, null, null);

Fuente: https://code.google.com/p/android/issues/detail?id=38282

Sathesh
fuente
11
Perfecto. Esta debería ser la solución a esta pregunta.
Hechicero
Esta solución no me funciona en un Nexus 7, Android 4.4.2, que se conecta a una Mac. Estoy creando una nueva carpeta en un almacenamiento externo y almacenando archivos en esa carpeta. Si solo ejecuto esto en los archivos de la carpeta, la Mac no muestra nada. Si también lo ejecuto en mi nuevo directorio, la Mac muestra que mi directorio es un archivo 4k (y no un directorio). También he intentado llamar context.sendBroadcast()sin ningún resultado.
Joe Lapp
Simplemente jugué con la realización de escaneos de medios y la transmisión de archivos creados en el directorio de descargas estándar, y nunca aparecieron al conectarme a la Mac.
Joe Lapp
¡Ah! Esto no se puede hacer desde onDestroy (). Funciona si lo hago en otro lugar. Puedo hacerlo en el momento en que creo el archivo, pero luego el navegador de archivos del escritorio muestra un tamaño de cero bits. Aun así, cuando copio el archivo, se copia todo el archivo.
Joe Lapp
Funciona con 8.1. Los archivos eliminados desaparecen solo después de reiniciar. Con esto, al menos los archivos escritos aparecen inmediatamente en el Explorador de archivos del sistema montado.
Midson
5

Después de pasar horas en este problema, lo resolví así:

private void rescanFolder(String dest) {
    // Scan files only (not folders);
    File[] files = new File(dest).listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.isFile();
        }
    });

    String[] paths = new String[files.length];
    for (int co=0; co< files.length; co++)
        paths[co] = files[co].getAbsolutePath();

    MediaScannerConnection.scanFile(activity, paths, null, null);

    // and now recursively scan subfolders
    files = new File(dest).listFiles(new FileFilter() {
        @Override
        public boolean accept(File pathname) {
            return pathname.isDirectory();
        }
    });

    for (int co=0; co<files.length; co++)
        rescanFolder(files[co].getAbsolutePath());
} 

El problema es que solo debe escanear archivos (no carpetas) y luego repetir de forma recursiva para cada fubfolder

EDITAR Además, si no desea que se agreguen imágenes a su álbum de fotos (sino que solo su contenido aparezca en el protocolo mtp), recuerde colocar un .nomediaarchivo vacío en su carpeta antes de volver a escanearlo, así:

new File(myFolder + File.separator + ".nomedia").createNewFile();
rescanFolder(myFolder);
lviggiani
fuente
Respuesta muy útil, pude usarlo de forma recursiva y ahora veo todos los archivos recién creados en MTP. De todos modos, ¿cómo lidiar con la desvinculación del servicio? Recibo un error ServiceConnectionLeaked: "La actividad se filtró ServiceConnection android.media.MediaScannerConnection@42164d98 que originalmente estaba enlazada aquí". Cualquier idea sobre cómo resolverlo desde el uso de MediaScannerConnection.scanFolder () estáticamente no hay posibilidad de desconectar () el servicio vinculado ...
Andre
3

En Xperia Z, el siguiente código funcionó bien:

  String screenShotFile = "....";
  activity.sendBroadcast(new Intent(
        Intent.ACTION_MEDIA_MOUNTED, Uri
                .fromFile(screenShotFile)));

para 4.4+ uso:

activity.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                                Uri.fromFile(screenShotFile)));

(lamentablemente no recuerdo si lo he probado lo suficientemente bien)

http://commonsware.com/blog/2013/11/06/android-4p4-permission-regressions.html

Marcinj
fuente
3

La mejor solución que encontré para el error mencionado en la respuesta aceptada es copiar datos del sistema operativo Android a otra máquina / servidor (Linux, MacOS, Windows) usando SSH.

  • Asegúrese de que el dispositivo (Android) y la máquina (donde desea copiar los datos) sean accesibles por IP o nombre de host, por ejemplo, conectándolos a la misma red wifi.

Opcional y recomendado

  • Conecte el dispositivo Android mediante conexión compartida USB. Esto asegura una velocidad rápida debido a la conexión por cable y garantiza que ambas direcciones IP sean visibles entre sí porque ambas están en la misma red.

En el dispositivo Android

  • Instale un servidor SSH. SSHelper funcionó como un encanto
  • Ejecute SSHelper y vaya a la pestaña de configuración para obtener la dirección IP, el puerto y la contraseña. En el siguiente ejemplo, son 192.168.1.5, 2222 y 'admin'.
  • La contraseña predeterminada es admin, pero si decide cambiarla, presione el botón "Reiniciar servidor con nuevos valores" después de cambiarla.

En la maquina

  • Instale rsync. Si usa Ubuntu, ya está instalado por defecto.
  • Abra un shell y escriba el siguiente comando. Cambie la dirección IP y el puerto a sus valores

rsync -avzhP --inplace --info=progress2 -e 'ssh -p 2222' 192.168.1.5:/storage/emulated/0/DCIM/Camera/ /home/username/path/to/pics/

  • obtendrá el siguiente mensaje, ingrese su contraseña

SSHelper Version 8.5 Copyright 2014, P. Lutus Default password is "admin" (recommend: change it) [email protected]'s password: admin receiving incremental file list

Las otras sugerencias no me funcionaron:

  • El dispositivo no admite el uso del modo de almacenamiento USB en lugar de MTP (como muchos otros dispositivos más nuevos).
  • No había ninguna opción en mi sistema operativo (Android 6.0.1) para borrar los datos de la aplicación "Almacenamiento multimedia".
  • Otros métodos de compartir archivos a través de la red tenían sus inconvenientes. FTP no garantiza la integridad de los archivos. Si se interrumpe la conexión, sobrescribe u omite todos los archivos, por lo que es posible que uno de los archivos esté incompleto. Otros protocolos pueden ser difíciles de instalar y otras aplicaciones pueden usar protocolos propietarios.
Defensor orgánico
fuente
2

aviso / almacenamiento / emulado. Android 4.2 tiene algunas cosas divertidas emuladas de acceso por aplicación / usuario, por ejemplo, una / sdcard / separada para cada usuario. Intente mover el archivo a / sdcard / en lugar de la sdcard emulada que se muestra.

Adam Weld
fuente
11
todo es un enlace de /storage/emulated/legacytodos modos, que en sí mismo es un enlace al /mnt/shell/emulated/0que contiene el archivo.
Moonlightcheese
2

El código simple propuesto para cuestionar ¿Cómo puedo actualizar MediaStore en Android? realiza la actualización necesaria de MediaStore, si se llama después de colocar un archivo en el almacenamiento externo. El contenido de mi Nexus 4 se actualiza instantáneamente en el explorador de archivos de Windows 7.

Stephan
fuente
Recién experimentado, que podría dejar de actualizarse eventualmente.
Stephan
1

Necesitaba crear un directorio y copiar algunos archivos de muestra para mi aplicación. Después de muchos experimentos e investigaciones, el siguiente procedimiento funcionó perfectamente para mí:

1) Directorio creado usando File.mkdir ().

2) Copie los archivos en el directorio y ejecute MediaScanner en cada archivo.

MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, null, null);

3) Ejecute MediaScanner en el directorio.

MediaScannerConnection.scanFile(context, new String[]{directory.getAbsolutePath()}, null, null);

Resultado: los archivos y el directorio aparecen instantáneamente en la PC a través de MTP.

Chebyr
fuente
Escanear tanto el directorio como el archivo específico creado funcionó para mí. También puede combinar las dos llamadas preparando una matriz String [] de dos elementos donde se enumeran tanto el archivo como el padre. Véase también stackoverflow.com/a/25086535/911550
parvus
1

Tuve un problema similar con mi OneplusOne:

Después de la actualización del software (a 6.0.1) no pude ver las imágenes de mi cámara cuando me conecté a la computadora (PTP y MTP). Tanto SDRescan como SDscanner de la aplicación no tuvieron ningún efecto.

Mi solución fue copiar todas las imágenes de DCIM a otra carpeta usando la terminal o cualquier aplicación de Explorador de archivos en el teléfono. Al conectarme a la computadora, pude ver los archivos copiados ... los moví a mi computadora y borré la carpeta de mi cámara. No hay una solución permanente, pero me solucionó el problema al menos hasta que haga la siguiente copia de seguridad. = D

Michael Saiz
fuente
0

Las respuestas anteriores están bien para crear el archivo. Si luego elimina el archivo y desea que ese cambio también se refleje, puede realizar una de las siguientes acciones; Primero veamos dos soluciones que parecen funcionar, pero que causarán problemas en algunos dispositivos. El primero es escanear el archivo eliminado:

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(file)));

Esto funciona en muchos dispositivos para archivos eliminados, pero en algunos dispositivos en realidad hará que se cree un nuevo archivo de 0 bytes, que probablemente no sea lo que desea. En ese caso, si está ejecutando en <4.4 KitKat, puede hacer esto:

context.sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.fromFile(folder)));

Donde carpeta es igual a file.getParentFile (). Desafortunadamente, en KitKat 4.4 y superior, esto hará que se lance una SecurityException, por lo que para esos dispositivos, puede intentar eliminar directamente desde Media Store:

final Uri externalFilesUri = Files.getContentUri("external");
context.getContentResolver().delete(externalFilesUri, Files.FileColumns.DATA + "=?", new String[] {file.getAbsolutePath()});

Probé este como una solución para que ACTION_MEDIA_MOUNTED no funciona en KitKat, y funciona en mis pruebas en el Nexus 5.

Aprenda OpenGL ES
fuente
0

Recientemente me enfrenté al mismo problema, pero algunas investigaciones adicionales ayudaron a encontrar archivos ocultos. Parece que Google ha realizado algunos cambios en la estructura de almacenamiento. Todos estos archivos se movieron a otra carpeta.This Computer\HTC One\Internal Storage\storage\emulated\0 . Pero es extraño que no se hayan movido todos los archivos.

Android 4.4.2

Aray Karjauv
fuente
0

De la documentación aquí , debe llamar a MediaScannerConnection.scanFile:

// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(this,
        new String[] { file.toString() }, null,
        new MediaScannerConnection.OnScanCompletedListener() {
    public void onScanCompleted(String path, Uri uri) {
        Log.i("ExternalStorage", "Scanned " + path + ":");
        Log.i("ExternalStorage", "-> uri=" + uri);
    }
});
Luca
fuente