Скажем, у вас есть такой метод:
public boolean saveFile (Url url, String content) {
// save the file, this can be done a lot of different ways, but
// basically the point is...
return save_was_successful;
}
В вашем приложении, если вы хотите сохранить файл во внешнем хранилище, вы делаете что-то вроде...
if (saveFile(external_storage_url, "this is a test")) {
// yay, success!
} else { // notify the user something was wrong or handle the error }
Это упрощенный пример, поэтому не приходите в мой вопрос о блокировке пользовательского интерфейса, правильной обработке исключений и т.д. Если вам не нравится сохранение файлов, вы можете представить себе getContact()
или getPhoneState()
или что-то еще, Дело в том, что это операция, требующая разрешения, которая возвращает некоторое значение (значения) и используется во всем приложении.
В Android <= Lollipop, если пользователь установил и согласился предоставить android.permission.WRITE_EXTERNAL_STORAGE
или что-то еще, все будет хорошо.
Но в новой модели разрешения Marshmallow (API 23) во время исполнения, прежде чем вы сможете сохранить файл во внешнем хранилище, вы должны (1) проверить, разрешение было предоставлено. Если нет, возможно (2) показать обоснование для запроса (если думает, что это хорошая идея) с тостом или что угодно и (3) попросить пользователя предоставить разрешение через диалог, а затем в основном сидеть сложа руки и ждать обратного вызова...
(так что ваше приложение сидит, ждет...)
(4) Когда пользователь, наконец, отвечает на диалог, срабатывает метод onRequestPermissionsResult(), и теперь ваш код (5) должен просеять через WHICH permission, они фактически отвечают на, сказал ли пользователь "да" или нет (насколько мне известно, нет способ обработки "нет" по сравнению с "нет и не спрашивать снова" ), (6) выяснить, что они пытались выполнить, в первую очередь, что вызвало весь процесс запроса-разрешения, чтобы программа могла наконец, (7) идти вперед и делать это.
Чтобы знать, что пользователь пытался выполнить на шаге (6), необходимо предварительно передать специальный код ( "запрос запроса разрешений" ), который описан в документы как идентификатор типа запроса на разрешение (камера/контакт/и т.д.), но мне кажется, что это скорее "конкретно, что вы пытались сделать, когда вы поняли, что вам нужно будет запрашивать разрешения", при условии, что один и тот же номер разрешения/группы может использоваться для нескольких целей в вашем коде, поэтому вам нужно будет использовать этот код для возврата к соответствующему месту после получения разрешения.
Я мог бы полностью недопонимать, как это должно работать, поэтому, пожалуйста, дайте мне знать, если я уйду, но, тем не менее, я не уверен, как даже думать о том, чтобы сделать все вышеперечисленное с методом saveFile()
, описанным ранее, из-за асинхронной части "ждать ответа пользователя". Идеи, которые я рассмотрел, довольно хаки и, безусловно, ошибочны.
Сегодня Подкаст для разработчиков Android намекнул, что за углом может быть синхронное решение, и даже говорили о волшебном одноэтапном альт-вводе типа "добавить запрос разрешения" в Android Studio. Тем не менее, как процесс разрешения времени выполнения может быть перенесен в saveFile()
или что-то еще - я что-то думаю по следующим направлениям:
public boolean saveFile(Url url, String content) {
// this next line will check for the permission, ask the user
// for permission if required, maybe even handle the rationale
// situation
if (!checkPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
R.string.permission_storage_rationale))
{
return false; // or throw an exception or whatever
} else {
// try to save the file
return save_was_successful;
}
}
Таким образом, выше checkPermission()
не удастся, если пользователь не имеет и также отказался предоставить разрешение. Возможно, можно было бы использовать цикл вокруг checkPermission()
, чтобы попытаться запросить до 3-х раз или что-то в этом роде, или лучше было бы, если бы этот метод обрабатывался здравомыслящей не-раздражающей политикой.
Возможно ли такое? Желаемое? Будет ли такое решение блокировать поток пользовательского интерфейса? Из подкаста это звучало так, что у Google может быть такое решение, как это происходит "за углом", но я хотел получить мысли о том, есть ли что-то - класс удобства, образец, что-то, что не включает всех, кто должен рефакторинг всех разрешающих действия операций, которые, как я должен предположить, могут стать довольно грязными.
Извините за длинный вопрос, но я хотел быть максимально полным. Я отведу свой ответ с воздуха. Спасибо!
Обновление. Ниже приведена транскрипция из приведенного выше подкаста.
Слушайте около 41:20. В этом обсуждении:
Грубая транскрипция:
Tor Norbye (команда Tools): "Так кажется, что для разработчиков не должно быть много работы. Но я понимаю, что часть проблемы заключается в том, что это не синхронные вызовы, так?" Итак, что вы имеете на самом деле изменить способ написания вашей деятельности, чтобы иметь обратный вызов - так что это действительно любопытно как конечный автомат, где... для этого состояния вы - "
Poiesz (менеджер продукта):" Ах, я думал, что есть возможность синхронного ответа -"
Norbye: "О, это сделает вещи..."
Poiesz: "Я могу поговорить с людьми внутри. Я вспоминаю дискуссию об синхронном, но мы можем это выяснить".
Norbye: "Да, на самом деле мы должны, вероятно, сделать это в инструментах. Где у вас есть простой рефакторинг..."
Затем он говорит об использовании аннотаций в инструментах, чтобы определить, какие API требуют разрешений.. (что на данный момент не работает с этой большой ИМО) и как он хочет, чтобы инструменты когда-либо фактически генерировали требуемый код, если он находит непроверенный "опасный" вызов метода:
Norbye: "... тогда, если вы тоже на M, он скажет:" Эй, вы действительно проверяете это разрешение или вы ловите исключения безопасности? ", а если нет, мы" Скажем, вам, вероятно, нужно что-то сделать для запроса разрешения здесь ". Я бы хотел, чтобы это было быстрым решением, где вы можете пойти" CHING! ". и он вставляет все нужные вещи для запроса, но, как все было обратно, когда я смотрел, это требовало реструктуризации многих вещей: добавления интерфейсов и обратных вызовов, а также изменения потока и чего мы не могли сделать. простой синхронный режим как временная вещь или постоянная вещь, которая была бы [велика]".