2013-11-25 3 views
0

Я внедряю новый API Storage Access Framework в свое приложение. Кажется, что все работает хорошо, за исключением одной мелочи. Когда я использую сборщик документов, чтобы открыть файл из моего собственного приложения (скажем, из другой учетной записи в приложении), openDocument в моей реализации DocumentsProvider вызывается в основном потоке. Это нормально, если запрошенный файл был кэширован локально, но если это не так, то выполняется сетевой запрос, результатом которого является NetworkInMainThreadException. Интересно отметить, что в документации упоминается «Это нормально, чтобы выполнять сетевые операции в этом методе для загрузки документа». Это известная ошибка, и если да, то кто-нибудь знает об этом?Android DocumentsProvider: openDocument вызывается в основном потоке

Вот мой код для запуска сборщика:

Intent target = new Intent(Intent.ACTION_OPEN_DOCUMENT); 
target.setType("*/*"); 
target.addCategory(Intent.CATEGORY_OPENABLE); 
final Intent intent = Intent.createChooser(target, getString(R.string.document_choose)); 
try { 
    startActivityForResult(intent, SELECT_FILE_REQUEST_CODE); 
} catch (ActivityNotFoundException e) { 
    e.printStackTrace(); 
} 

Затем, когда пользователь выбрал файл, это примерно как я обрабатывать openDocument:

@Override 
public ParcelFileDescriptor openDocument(final String documentId, String mode, 
     CancellationSignal signal) throws FileNotFoundException { 

    final File file = getFileFromId(documentId); 
    if(!file.exists()) { 
     // This is where I have problems 
     if("main".equalsIgnoreCase(Thread.currentThread().getName())) { 
      throw new FileNotFoundException("File has not been cached locally."); 
     } else { 
      downloadFile(app, file, document, folder); 
     } 
    } 
} 

Обратите внимание на проверку для того вызова на основной нити. Этого не происходит, когда внешнее приложение использует мое приложение для выбора файла, так как openDocument затем вызывается в фоновом потоке. Это происходит только тогда, когда я пытаюсь выбрать файл из своего собственного приложения (но из другой учетной записи и, следовательно, другого ROOT).

Однако, когда я попытался сделать то же самое на Google Диске (то есть, запустил приложение, а затем использовал свой собственный сборщик, чтобы выбрать файл), он, казалось, мог загрузить файл по сети без сбоев приложение.

ответ

2

Хорошо, я понял. Уловка openDocument косвенно вызывается (через ContentResolver) из моего Activity's onActivityResult. Когда я позвонил openInputStream() на ContentResolver, я вызывал его из основного потока, который в свою очередь вызывал openDocument в основном потоке. Исправлена ​​проблема с переносом этого вызова в фоновый поток.

документация упоминает это в предыдущем абзаце, в фрагменте кода:

Обратите внимание, что вы не должны делать эту операцию в потоке пользовательского интерфейса. Сделайте это в фоне, используя AsyncTask.

+0

Но некоторые из таких приложений, как Gmail, делают это на главной теме, что приведет к сбою в так называемом NetworkInMainThreadException. – Boopathy

Смежные вопросы