Nexus 4 nie wyświetla plików przez MTP

80

Próbuję po prostu zapisać prosty plik XML na kartę SD i zauważyłem, że mój Nexus 4 zapisuje plik, ale nie można go przeglądać za pomocą protokołu MTP w systemie Windows 7.

kod:

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();
    }
}

Widzę plik w telefonie za pomocą Astro File Manager:

Zrzut ekranu

ale Windows tego nie widzi ...:

Zrzut ekranu

adb shell w katalogu pokazuje:

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

Co się dzieje z moim Nexusem 4? Dlaczego ukrywa moje rzeczy przed systemem Windows?

ser księżycowy
źródło
1
Myślałem, że robię coś złego. Teraz wiem, że nie jestem sam.
neverMind9

Odpowiedzi:

72

Wydaje się, że jest to znany problem wpływający na dostęp do plików USB w systemie Android przez protokół MTP . Pamięć podręczna MTP staje się nieaktualna do momentu ponownego uruchomienia telefonu.

Obejście jest:

  • Wyczyść dane aplikacji „Media Storage”
  • Użyj aplikacji SDrescan lub SD Scanner (działa również w systemie Android 4.4 / 5, dostępnym w F-Droid ), aby wymusić aktualizację

Lub po prostu unikaj używania USB. Problem nie dotyczy innych metod uzyskiwania dostępu do plików. Na przykład spróbuj AirDroid do przesyłania plików.


Uwaga: to nie działa w systemie Android 5.0.2: po wyczyszczeniu „Media Storage” i użyciu skanera SD Rescanner foldery pojawiają się w systemie Windows 7 jako nieotwarte pliki 4K. Jedynym rozwiązaniem w tym momencie jest ponowne wyczyszczenie Media Storage i ponowne uruchomienie urządzenia

Kevin Panko
źródło
2
Zainstaluj SDrescan, uruchom go: naprawiono!
Wielkie
To się nie działo wcześniej, ale dzisiaj tak. BTW, restart powinien działać IDK, dlaczego to nie działa.
Muhammad Babar
To dziwne, po ponownym uruchomieniu telefonu 3 razy się pojawił.
Muhammad Babar
To nie działa w systemie Android 5.0.2: po wyczyszczeniu „Media Storage” i użyciu skanera SD Rescanner foldery pojawiają się w systemie Windows 7 jako pliki 4K, których nie można otworzyć. Jedynym rozwiązaniem w tym momencie jest ponowne wyczyszczenie Media Storage i ponowne uruchomienie urządzenia.
Antonio
To również nie działało na Nexusie 7 z Androidem 4.4.2. Mój Mac zgłasza, że ​​mój katalog niestandardowy to plik 4k.
Joe Lapp
44

Możesz użyć następującego kodu po zamknięciu pliku

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

Źródło: https://code.google.com/p/android/issues/detail?id=38282

Sathesh
źródło
11
Doskonały. To powinno być rozwiązanie tego pytania.
Sorcerer
To rozwiązanie nie działa dla mnie na Nexusie 7, Android 4.4.2, łączącym się z komputerem Mac. Tworzę nowy folder w pamięci zewnętrznej i przechowuję pliki w tym folderze. Jeśli uruchomię to tylko na plikach w folderze, Mac nic nie pokaże. Jeśli uruchomię go również w moim nowym katalogu, Mac pokaże, że mój katalog to plik 4k (a nie katalog). Próbowałem też dzwonić context.sendBroadcast()bez skutku.
Joe Lapp
Po prostu bawiłem się skanowaniem multimediów i nadawaniem plików utworzonych w standardowym katalogu Pobrane i nigdy nie pojawiały się po podłączeniu do komputera Mac.
Joe Lapp
Ach. Nie można tego zrobić z onDestroy (). Działa, jeśli robię to gdzie indziej. Mogę to zrobić w momencie tworzenia pliku, ale wtedy przeglądarka plików na komputerze pokazuje rozmiar zerowy. Mimo to, kiedy kopiuję plik, kopiuje on cały plik.
Joe Lapp
Działa z 8.1. Usunięte pliki znikają dopiero po ponownym uruchomieniu. Dzięki temu przynajmniej zapisane pliki pojawiają się natychmiast w przeglądarce plików zamontowanego systemu.
Midson,
5

Po spędzeniu godzin na tym problemie rozwiązałem tak:

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());
} 

Chodzi o to, że musisz skanować tylko pliki (nie foldery), a następnie powtarzać rekurencyjnie dla każdego fubfolderu

EDYTUJ Ponadto, jeśli nie chcesz, aby zdjęcia były dodawane do albumu ze zdjęciami (ale tylko zawartość była wyświetlana w protokole mtp), pamiętaj, aby umieścić pusty .nomediaplik w folderze przed ponownym skanowaniem, na przykład:

new File(myFolder + File.separator + ".nomedia").createNewFile();
rescanFolder(myFolder);
lviggiani
źródło
Bardzo przydatna odpowiedź, mogłem jej używać rekurencyjnie i teraz widzę wszystkie nowo utworzone pliki na MTP. Zresztą, jak sobie radzić z rozpinaniem usługi? Otrzymuję błąd ServiceConnectionLeaked: „Wyciekła aktywność ServiceConnection android.media.MediaScannerConnection@42164d98, która została pierwotnie powiązana tutaj”. Każdy pomysł, jak to rozwiązać, ponieważ użycie MediaScannerConnection.scanFolder () statycznie nie ma szans na odłączenie () powiązanej usługi ...
Andre
4

Najlepszym obejściem błędu wymienionego w zaakceptowanej odpowiedzi, jakie znalazłem, jest skopiowanie danych z systemu operacyjnego Android na inny komputer / serwer (Linux, MacOS, Windows) przy użyciu protokołu SSH.

  • Upewnij się, że urządzenie (Android) i maszyna (na którą chcesz skopiować dane) są osiągalne przez adres IP lub nazwę hosta, na przykład łącząc je z tą samą siecią Wi-Fi.

Opcjonalne i zalecane

  • Podłącz urządzenie z systemem Android za pomocą tetheringu przez USB. Zapewnia to dużą prędkość dzięki połączeniu przewodowemu i gwarantuje, że oba adresy IP są dla siebie widoczne, ponieważ oba znajdują się w tej samej sieci.

Na urządzeniu z Androidem

  • Zainstaluj serwer SSH. SSHelper działał jak urok
  • Uruchom SSHelper i przejdź do karty konfiguracji, aby uzyskać adres IP, port i hasło. W poniższym przykładzie są to 192.168.1.5, 2222 i „admin”.
  • Domyślne hasło to admin, ale jeśli zdecydujesz się je zmienić, po zmianie naciśnij przycisk „Restartuj serwer z nowymi wartościami”

W maszynie

  • Zainstaluj rsync. Jeśli używasz Ubuntu, jest już domyślnie zainstalowany.
  • Otwórz powłokę i wpisz następujące polecenie. Zmień adres IP i port na swoje wartości

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

  • pojawi się następujący monit, wprowadź hasło

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

Inne sugestie nie zadziałały dla mnie:

  • Używanie trybu pamięci USB zamiast MTP nie jest obsługiwane przez urządzenie (jak wiele innych nowszych urządzeń).
  • W moim systemie operacyjnym (Android 6.0.1) nie było możliwości wyczyszczenia danych aplikacji „Media Storage”.
  • Inne metody udostępniania plików w sieci mają swoje wady. FTP nie zapewnia integralności plików. Jeśli połączenie zostanie zerwane, nadpisuje lub pomija wszystkie pliki, więc jeden z plików może być niekompletny. Inne protokoły mogą być trudne do zainstalowania, a inne aplikacje mogą korzystać z zastrzeżonych protokołów.
Rzecznik organiczny
źródło
3

Na Xperii Z poniższy kod działał dobrze:

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

do użytku w wersji 4.4+:

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

(niestety nie pamiętam, czy wystarczająco dobrze to przetestowałem)

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

marcinj
źródło
2

zawiadomienie / przechowywanie / emulowane. Android 4.2 ma kilka funky emulowanych elementów dostępu do aplikacji / użytkownika, na przykład oddzielny / sdcard / dla każdego użytkownika. Spróbuj przenieść plik do / sdcard / zamiast wyświetlanej emulowanej karty sdcard.

Adam Weld
źródło
11
i tak wszystko jest linkiem do /storage/emulated/legacy, co samo w sobie jest linkiem do /mnt/shell/emulated/0którego zawiera plik.
moonlightcheese
2

Prosty kod zaproponowany do pytania Jak mogę odświeżyć MediaStore na Androidzie? wykonuje niezbędną aktualizację MediaStore, jeśli zostanie wywołana po umieszczeniu pliku w pamięci zewnętrznej. Zawartość mojego Nexusa 4 jest natychmiast odświeżana w eksploratorze plików Windows 7.

Stephan
źródło
Właśnie doświadczyłem, że w końcu może przestać się aktualizować.
Stephan
1

Musiałem utworzyć katalog i skopiować kilka przykładowych plików dla mojej aplikacji. Po wielu eksperymentach i badaniach następująca procedura zadziałała dla mnie bez zarzutu:

1) Utworzono katalog za pomocą File.mkdir ().

2) Skopiuj pliki do katalogu i uruchom MediaScanner na każdym pliku.

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

3) Uruchom MediaScanner w katalogu.

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

Wynik: pliki i katalog pojawią się natychmiast na komputerze PC przez MTP.

Czebyr
źródło
Skanowanie zarówno katalogu, jak i utworzonego pliku zadziałało. Możesz również połączyć te dwa wywołania, przygotowując tablicę String [] składającą się z dwóch elementów, w której wymieniony jest zarówno plik, jak i rodzic. Zobacz także stackoverflow.com/a/25086535/911550
parvus
1

Miałem podobny problem z moim OneplusOne:

Po aktualizacji oprogramowania (do wersji 6.0.1) nie widziałem zdjęć z aparatu po podłączeniu do komputera (PTP i MTP). Zarówno SDRescan, jak i SDscanner aplikacji nie przyniosły żadnego efektu.

Moim rozwiązaniem było skopiowanie wszystkich zdjęć z DCIM do innego folderu za pomocą terminala lub dowolnej aplikacji Eksplorator plików w telefonie. Po podłączeniu do komputera mogłem zobaczyć skopiowane pliki. Przeniosłem je na komputer i wyczyściłem folder aparatu. Brak trwałego rozwiązania, ale rozwiązało to problem przynajmniej do czasu wykonania następnej kopii zapasowej. = D

Michael Saiz
źródło
0

Powyższe odpowiedzi są wystarczające do tworzenia pliku. Jeśli później usuniesz plik i chcesz, aby ta zmiana również została odzwierciedlona, ​​możesz wykonać jedną z następujących czynności; Omówmy najpierw dwa rozwiązania, które wydają się działać, ale mogą powodować problemy na niektórych urządzeniach. Pierwsza to przeskanowanie usuniętego pliku:

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

Działa to na wielu urządzeniach w przypadku usuniętych plików, ale na niektórych urządzeniach spowoduje utworzenie nowego pliku 0-bajtowego, co prawdopodobnie nie jest tym, czego chcesz. W takim przypadku, jeśli korzystasz z wersji <4.4 KitKat, możesz to zrobić:

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

Gdzie folder jest równy file.getParentFile (). Niestety w KitKat 4.4 i nowszych wersjach spowoduje to wyrzucenie wyjątku SecurityException, więc w przypadku tych urządzeń możesz spróbować usunąć bezpośrednio z Media Store:

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

Przetestowałem to jako obejście problemu ACTION_MEDIA_MOUNTED, który nie działa na KitKat, i działa w moich testach na Nexusie 5.

Naucz się OpenGL ES
źródło
0

Ostatnio napotkałem ten sam problem, ale dodatkowe badania pomogły znaleźć ukryte pliki. Wygląda na to, że Google dokonał pewnych zmian w strukturze przechowywania. Wszystkie te pliki zostały przeniesione do innego folderu This Computer\HTC One\Internal Storage\storage\emulated\0. Ale to dziwne, że nie wszystkie pliki zostały przeniesione.

Android 4.4.2

Aray Karjauv
źródło
0

Z dokumentacji tutaj , musisz wywoł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
źródło