2010-01-27 11 views
14

Interfejsy API dostawcy treści/resolwera zapewniają skomplikowany, ale niezawodny sposób przesyłania danych między procesami przy użyciu metod URI i openInputStream() i openOutputStream(). Dostawcy niestandardowych treści mają możliwość zastąpienia metody openFile() za pomocą niestandardowego kodu, aby skutecznie rozwiązać URI w postaci Stream; jednak sygnatura metody openFile() ma typ zwracany ParcelFileDescriptor i nie jest jasne, w jaki sposób można wygenerować poprawną reprezentację dynamicznie generowanej zawartości, aby powrócić z tej metody.Niestandardowy ContentProvider - openInputStream(), openOutputStream()

Returning a memory mapped InputStream from a content provider?

Czy istnieją przykłady realizacji ContentProvider.openFile() metodę zawartości dynamicznej w istniejącej bazie kodu? Jeśli nie, możesz zasugerować kod źródłowy lub proces, aby to zrobić?

Odpowiedz

1

MemoryFile obsługuje to, ale publiczny interfejs API nie został sfinalizowany.

+0

Czy planuje się zamienić konwersję między plikiem pamięci i w przyszłym? Coś w tym kierunku byłoby ładniejsze niż zaśmiecanie/zanieczyszczanie systemu plików plikami tymczasowymi o nieosiągalnym czasie życia. Może jest jakiś sposób, aby wykryć zamknięcie strumienia w ramach dostawcy treści, który może zapewnić nieco bezpieczniejszy sposób oczyszczania po sobie? Jestem zaniepokojony wysyłaniem załączników do klienta pocztowego (gmail/standaed), chociaż jestem pewien, że istnieją inne miejsca, w których mogą wystąpić te problemy. – hannasm

+1

Tak, MemoryFile.java ma obecnie 'publiczną metodę ParcelFileDescriptor getParcelFileDescriptor()'. Zostało to popełnione w ramach Doughnut, ale jak powiedział Jeff, wciąż nie jest jeszcze sfinalizowane. Potwierdziłem, że "koncepcja" przynajmniej działa i może być teraz wykonana za pomocą refleksji. Jest bardzo brudny i niezalecany :) Niestety, nawet 'ParcelFileDescriptor.fromSocket()' nie może być użyty, ponieważ 'Memory.isMemoryFile()' zgłasza wyjątek, ponieważ gniazdo nie jest ani PFD, ani plikiem pamięci. – Joe

+1

Ostrożnie z MemoryFile. Jeśli rozumiem to poprawnie, przechowuje całą zawartość pliku w pamięci, więc nie można używać plików większych niż dostępna pamięć. –

23

Sprawdź ten świetny przykładowy projekt od zawsze pomocnego CommonsWare. To pozwala tworzyć rurę ParcelFileDescriptor ze cokolwiek InputStream chcesz po jednej stronie, a aplikacja odbierająca z drugiej strony:

https://github.com/commonsguy/cw-omnibus/tree/master/ContentProvider/Pipe

Główne części tworzą rurę w openFile:

public ParcelFileDescriptor openFile(Uri uri, String mode) 
                 throws FileNotFoundException { 
    ParcelFileDescriptor[] pipe=null; 

    try { 
     pipe=ParcelFileDescriptor.createPipe(); 
     AssetManager assets=getContext().getResources().getAssets(); 

     new TransferThread(assets.open(uri.getLastPathSegment()), 
         new AutoCloseOutputStream(pipe[1])).start(); 
    } 
    catch (IOException e) { 
     Log.e(getClass().getSimpleName(), "Exception opening pipe", e); 
     throw new FileNotFoundException("Could not open pipe for: " 
      + uri.toString()); 
    } 

    return(pipe[0]); 
    } 

Następnie utwórz wątek, który utrzymuje rurę pełną:

static class TransferThread extends Thread { 
    InputStream in; 
    OutputStream out; 

    TransferThread(InputStream in, OutputStream out) { 
     this.in = in; 
     this.out = out; 
    } 

    @Override 
    public void run() { 
     byte[] buf = new byte[8192]; 
     int len; 

     try { 
      while ((len = in.read(buf)) > 0) { 
       out.write(buf, 0, len); 
      } 

      in.close(); 
      out.flush(); 
      out.close(); 
     } catch (IOException e) { 
      Log.e(getClass().getSimpleName(), 
        "Exception transferring file", e); 
     } 
    } 
} 
+3

Idealne właśnie to, czego szukałem ... – siliconeagle

+0

Używam lib innej firmy, która żąda plików za pośrednictwem dostawcy treści iz jakiegoś powodu dane na drugim końcu przychodzą (i tutaj ostrożnie mówię) inaczej, gdy zwracają ParcelFileDescriptor w ten sposób lub podczas używania pliku rzeczywistego, jak na przykład: ParcelFileDescriptor.open (privateFile, ParcelFileDescriptor.MODE_READ_ONLY) – TacB0sS

+1

Każdy pomysł, dlaczego czasami pojawia się błąd podczas korzystania z tego dostawcy z większą ilością żądań: java.io.IOException: write failed : EPIPE (Broken pipe) na libcore.io.IoBridge.write (IoBridge.java:502) na java.io.FileOutputStream.write (FileOutputStream.java:186) – Malachiasz

Powiązane problemy