0

FTP/CLoudRail을 사용하여 인터넷을 통해 파일에 액세스하는 앱을 만들고 있습니다. 파일을 열 때이 메서드를 사용하여 먼저 입력 스트림을 가져온 다음 ParcelFileDescriptor로 파싱합니다. 문제는 PDF 파일을 열 때 brokenPipe 오류가 발생한다는 것입니다.pdf 파일의 입력 스트림을 전달할 때 파손 된 파이프

다음
@Override 
public ParcelFileDescriptor openDocument(final String documentId, final String mode, 
             CancellationSignal signal) 
     throws FileNotFoundException { 
    Log.d(TAG,"Opening document"); 
    final CloudFile file = getFileForDocId(documentId); 
    final CloudConnection connection = getCloudConnection(documentId); 
    //TODO Open a file 
    try { 
     final boolean isWrite = (mode.indexOf('w') != -1); 
     if (isWrite) { 
      return null; 
     } else { 
      InputStream inputStream = connection.getConnectedClient().download(file.getPath()); 
      if(null != inputStream){ 
       return ParcelFileDescriptorUtil.pipeFrom(inputStream); 
      } 
     } 

     return null; 
    } catch (Exception e) { 
     CrashReportingManager.logException(e); 
     throw new FileNotFoundException("Failed to open document with id " + documentId + 
       " and mode " + mode); 
    } 
} 

가 ParcelFileDescriptorUtil입니다 :이 이미지와 같은 다른 파일 형식으로 발생하지 않습니다/텍스트 여기

내가 사용하는 코드 파일

public class ParcelFileDescriptorUtil { 
public static ParcelFileDescriptor pipeFrom(InputStream inputStream) 
     throws IOException { 
    final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); 
    final OutputStream output = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]); 

    new TransferThread(inputStream, output).start(); 

    return pipe[0]; 
} 

@SuppressWarnings("unused") 
public static ParcelFileDescriptor pipeTo(OutputStream outputStream) 
     throws IOException { 
    final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); 
    final InputStream input = new ParcelFileDescriptor.AutoCloseInputStream(pipe[0]); 

    new TransferThread(input, outputStream).start(); 

    return pipe[1]; 
} 

static class TransferThread extends Thread { 
    final InputStream mIn; 
    final OutputStream mOut; 

    TransferThread(InputStream in, OutputStream out) { 
     super("ParcelFileDescriptor Transfer Thread"); 
     mIn = in; 
     mOut = out; 
     setDaemon(true); 
    } 

    @Override 
    public void run() { 
     try { 
      IoUtils.copy(mIn, mOut); 
     } catch (IOException e) { 
      Log.e("TransferThread", "writing failed"); 
      CrashReportingManager.logException(e); 
     } finally { 
      IoUtils.flushQuietly(mOut); 
      IoUtils.closeQuietly(mIn); 
      IoUtils.closeQuietly(mOut); 
     } 
    } 
} 

public static int parseMode(String mode) { 
    final int modeBits; 
    if ("r".equals(mode)) { 
     modeBits = ParcelFileDescriptor.MODE_READ_ONLY; 
    } else if ("w".equals(mode) || "wt".equals(mode)) { 
     modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY 
       | ParcelFileDescriptor.MODE_CREATE 
       | ParcelFileDescriptor.MODE_TRUNCATE; 
    } else if ("wa".equals(mode)) { 
     modeBits = ParcelFileDescriptor.MODE_WRITE_ONLY 
       | ParcelFileDescriptor.MODE_CREATE 
       | ParcelFileDescriptor.MODE_APPEND; 
    } else if ("rw".equals(mode)) { 
     modeBits = ParcelFileDescriptor.MODE_READ_WRITE 
       | ParcelFileDescriptor.MODE_CREATE; 
    } else if ("rwt".equals(mode)) { 
     modeBits = ParcelFileDescriptor.MODE_READ_WRITE 
       | ParcelFileDescriptor.MODE_CREATE 
       | ParcelFileDescriptor.MODE_TRUNCATE; 
    } else { 
     throw new IllegalArgumentException("Bad mode '" + mode + "'"); 
    } 
    return modeBits; 
} 

@RequiresApi(api = Build.VERSION_CODES.KITKAT) 
public static ParcelFileDescriptor pipeFrom(InputStream inputStream, IThreadListener listener) 
     throws IOException { 
    ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createReliablePipe(); 
    ParcelFileDescriptor readSide = pipe[0]; 
    ParcelFileDescriptor writeSide = pipe[1]; 

    // start the transfer thread 
    new TransferThread2(inputStream, new ParcelFileDescriptor.AutoCloseOutputStream(writeSide), 
      listener) 
      .start(); 

    return readSide; 
} 

public static ParcelFileDescriptor pipeTo(OutputStream outputStream, IThreadListener listener) 
     throws IOException { 
    ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); 
    ParcelFileDescriptor readSide = pipe[0]; 
    ParcelFileDescriptor writeSide = pipe[1]; 

    // start the transfer thread 
    new TransferThread2(new ParcelFileDescriptor.AutoCloseInputStream(readSide), outputStream, 
      listener) 
      .start(); 

    return writeSide; 
} 

static class TransferThread2 extends Thread { 
    final InputStream mIn; 
    final OutputStream mOut; 
    final IThreadListener mListener; 

    TransferThread2(InputStream in, OutputStream out, IThreadListener listener) { 
     super("ParcelFileDescriptor Transfer Thread"); 
     mIn = in; 
     mOut = out; 
     mListener = listener; 
     setDaemon(true); 
    } 

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

     try { 
      while ((len = mIn.read(buf)) > 0) { 
       mOut.write(buf, 0, len); 
      } 
      mOut.flush(); // just to be safe 
     } catch (IOException e) { 
      Log.e("TransferThread", "writing failed"); 
      e.printStackTrace(); 
     } finally { 
      try { 
       mIn.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      try { 
       mOut.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     if (mListener != null) 
      mListener.onThreadFinished(this); 
    } 
} 

이상한 무엇 일반적으로 그 , 루트 권한이없는 경우에 발생합니다. 그러나 pdf를 표시하기 위해서는 당연히 그 필요는 없습니다.

12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err: java.io.IOException: write failed: EPIPE (Broken pipe) 
12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:  at libcore.io.IoBridge.write(IoBridge.java:558) 
12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:  at java.io.FileOutputStream.write(FileOutputStream.java:326) 
12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:  at com.tproductions.Openit.libcore.io.IoUtils.copyLarge(IoUtils.java:310) 
12-22 17:37:48.516 9112-9691/com.tproductions.Openit.pro W/System.err:  at com.tproductions.Openit.libcore.io.IoUtils.copy(IoUtils.java:283) 
12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:  at com.tproductions.Openit.misc.ParcelFileDescriptorUtil$TransferThread.run(ParcelFileDescriptorUtil.java:70) 
12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err: Caused by: android.system.ErrnoException: write failed: EPIPE (Broken pipe) 
12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:  at libcore.io.Linux.writeBytes(Native Method) 
12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:  at libcore.io.Linux.write(Linux.java:286) 
12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:  at libcore.io.BlockGuardOs.write(BlockGuardOs.java:345) 
12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err:  at libcore.io.IoBridge.write(IoBridge.java:553) 
12-22 17:37:48.517 9112-9691/com.tproductions.Openit.pro W/System.err: ... 4 more 
+0

대단히 감사합니다.하지만 Uri 및 MIME 형식이 아닌 입력 스트림을 사용하고 있습니다. 제가 누락 된 것이 있습니까? – Traabefi

+0

아니, 그냥 내부 클래스, 내 Util 클래스에서 thread2에서 볼 수있는 단순한 while 루프입니다. – Traabefi

답변

0

문제는 지금 해결 : 그런데

, 여기에 오류가 발생합니다. 이상하게도 그것이 내 애플 리케이션에서 PDF 파일을 여는 방식이었습니다. 새로운 InputStreamDataSource()를 전달하고 있었지만 예외가 발생한 입력 스트림을 닫았습니다. 이상하게도 충분히 작동합니다. 이제는 작동합니다.

관련 문제