2010-01-27 2 views
14

컨텐츠 제공자/해석기 API는 URI와 openInputStream()openOutputStream() 메소드를 사용하는 프로세스간에 데이터를 전송하는 복잡하지만 강력한 방법을 제공합니다. 사용자 지정 콘텐츠 공급자는 사용자 지정 코드로 openFile() 메서드를 재정의하여 URI를 Stream으로 효과적으로 해결할 수 있습니다. 그러나 openFile()의 메서드 서명에는 ParcelFileDescriptor 반환 형식이 있으며이 메서드에서 반환 할 동적 생성 콘텐츠에 대한 적절한 표현을 생성하는 방법이 명확하지 않습니다.사용자 정의 ContentProvider - openInputStream(), openOutputStream()

Returning a memory mapped InputStream from a content provider?

는 기존의 코드베이스에서 동적 콘텐츠에 대한 ContentProvider.openFile() 방법을 구현하는 사례가 있습니까? 그렇지 않다면 소스 코드를 제안하거나 프로세스를 제안 할 수 있습니까?

답변

1

MemoryFile은이를 지원하지만 공용 API가 마무리되지 않았습니다.

+0

메모리 파일과 메모리 사이에 변환을 포함시킬 계획이 있습니까? 미래에 parcelfiledescriptor? 이 줄을 따라 뭔가가 알려지지 않은 수명을 가진 임시 파일로 파일 시스템을 어수선하게 만들거나 오염시키는 것보다 좋을 것입니다. 아마도 콘텐츠 제공자 내에서 스트림을 닫는 것을 감지하여 스스로 안전하게 정리할 수있는 방법이 있습니까? (gmail/standaed) 이메일 클라이언트에 첨부 파일을 보내는 것에 관심이 있습니다. 이러한 문제가 발생할 수있는 다른 장소가 있다고 확신합니다. – hannasm

+1

예, MemoryFile.java에는 현재'ParcelFileDescriptor getParcelFileDescriptor()'메소드가 있습니다. 이것은 도넛 (Donut)의 일환으로 이루어졌지만 제프 (Jeff)가 말했듯이 아직 완성되지 않았습니다. "개념"이 적어도 작동하고 리플렉션을 사용하여 현재 완료 될 수 있음을 확인했습니다. 그것은 매우 더럽지 만 권장하지는 않습니다. 불행히도, 'Memory.isMemoryFile()'는 소켓이 PFD 나 메모리 파일이 아니기 때문에'Memory.isMemoryFile()'이 예외를 던 졌기 때문에'ParcelFileDescriptor.fromSocket()'도 사용할 수 없습니다. – Joe

+1

MemoryFile을 사용할 때주의해야합니다. 올바르게 이해하면 파일의 전체 내용을 메모리에 저장하므로 사용 가능한 메모리보다 큰 파일을 사용할 수 없습니다. –

23

언제나 도움이되는 CommonsWare에서 위대한 예제 프로젝트를 확인하십시오. 그것은 당신이 한쪽에 원하는대로의 InputStream과 된 ParcelFileDescriptor 파이프를 만들 수 있습니다, 다른 쪽의 수신 응용 프로그램 :

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

핵심 부품 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]); 
    } 

그런 다음 파이프를 가득 채우는 스레드를 만듭니다.

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

내가 찾던 것을 완벽하게 ... – siliconeagle

+0

콘텐츠 제공 업체를 통해 파일을 요청하는 제 3 자 lib를 사용하고 다른 이유로 데이터를 가져 오는 경우 (다른 말로하면주의 깊게 읽었습니다) 다르게 반환 할 때 ParcelFileDescriptor 이런 식으로 또는 실제 파일을 사용할 때 : ParcelFileDescriptor.open (privateFile, ParcelFileDescriptor.MODE_READ_ONLY) – TacB0sS

+1

더 많은 양의 요청으로이 제공자를 사용할 때 때때로 오류가 발생하는 이유는 무엇입니까? java.io.IOException : 쓰기에 실패했습니다. : EPIPE (깨진 파이프) at libcore.io.IoBridge.write (IoBridge.java:502) at java.io.FileOutputStream.write (FileOutputStream.java:186) – Malachiasz

관련 문제