1

Мое приложение копирует кучу файлов, и запрос приходит как список. У меня есть ContentProvider, поэтому мне нужно скопировать файл и зарегистрировать его у поставщика файлов. Я пробовал две вещи - откручивание AsyncTask для каждой копии файла и отключение одной AsyncTask для обработки всех них. Проблема, с которой я сталкиваюсь, заключается в том, что с несколькими AsyncTasks телефон действительно замедляется на секунду или два. Однако при работе с файлами, один за другим, я получаю IOException - дескриптор файла закрыт:Вызывается копирование файлов на Android. Java.io.IOException: дескриптор файла закрыт

   D .doInBackground() - outputUri is /photo/20150602004304409 
       D .doInBackground() - outputUri is /photo/20150602004304421 
       D .doInBackground() - outputUri is /photo/20150602004304423 
       D .doInBackground() - outputUri is /photo/20150602004304426 
       D .doInBackground() - outputUri is /photo/20150602004304428 

       E java.io.IOException: File descriptor closed 
       E  at libcore.io.Posix.writeBytes(Native Method) 
       E  at libcore.io.Posix.write(Posix.java:223) 
       E  at libcore.io.BlockGuardOs.write(BlockGuardOs.java:313) 
       E  at libcore.io.IoBridge.write(IoBridge.java:497) 
       E  at java.io.FileOutputStream.write(FileOutputStream.java:186) 

Это мой код:

Uri outputUri = Uri.parse(String.format(path, context.getPackageName())); 
mOutputUri = context.getContentResolver().insert(outputUri, null); 
if (AndroidHelper.isGingerBreadMR1()) { 
    execute(); 
} else { 
    executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} 

< ...>

 InputStream inputStream = null; 
     OutputStream outputStream = null; 
     boolean error = false; 
     Log.d(TAG,".doInBackground() - outputUri is "+mOutputUri.getPath()); 
     try { 
      inputStream = mContext.getContentResolver().openInputStream(mInputUri); 
      FileDescriptor fileDescriptor = getMediaFileDescriptor(mOutputUri); 
      if (fileDescriptor != null) { 
       outputStream = new FileOutputStream(fileDescriptor); 
       byte[] buffer = new byte[1024]; 
       int read; 
       while ((read = inputStream.read(buffer)) != -1) { 
        outputStream.write(buffer, 0, read); 
       } 
      } 
     } catch (IOException e) { 
      Log.e(TAG, ".doInBackground - exception caught while copying the file",e); 
      error = true; 
     } finally { 
      try { 
       if (inputStream != null) { 
        inputStream.close(); 
       } 
       if (outputStream != null) { 
        outputStream.close(); 
       } 
      } catch (IOException e) { 
       Log.e(TAG, ".doInBackground - exception caught while closing input stream",e); 
       error = true; 
      } 
     } 
     return (error) ? mInputUri : mOutputUri; 

getMediaFileDescriptor выглядит например:

private FileDescriptor getMediaFileDescriptor(Uri outputUri) { 
    try { 
     return mContext.getContentResolver().openFileDescriptor(outputUri, "w") 
       .getFileDescriptor(); 
    } catch (FileNotFoundException e) { 
     Log.e(TAG, ".getMediaFileDescriptor() - Error opening media output stream", e); 
    } 
    return null; 
} 
+0

Вы уверены, что не используете тот же дескриптор файла снова и снова. Дескриптор файла становится недействительным после закрытия потока. – ata

+0

Также поделитесь выходом logcat – ata

+0

Выход uri - это новый uri каждый раз - я это проверил. Кроме того, выполнение простой toString объекта fileDescriptor возвращает разные значения ... Если contentresolver не повторно использует дескрипторы файлов под обложками? Есть ли способ проверить или защитить от этого? – vkislicins

ответ

0

У меня есть проблема, это не хорошо, но вы должны очистить поток, прежде чем закрыть его.

while ((read = inputStream.read(buffer)) != -1) { 
       outputStream.write(buffer, 0, read); 
       outputStream.Flush(); 
      } 

моя проблема решена этим кодом.

0

Вы также должны позвонить по телефону .close() на номер ParcelFileDescriptor, возвращенный getContentResolver().openFileDescriptor, когда вы закончите с этим.