- Русские Блоги
- Несколько способов реализовать таймеры в Android
- предисловие
- Механизм сообщений Android
- текст
- AlarmManager
- Резюме преимуществ
- Применимая сцена
- Handler
- Резюме преимуществ
- Применимая сцена
- Timer
- Резюме преимуществ
- Применимая сцена
- Thread
- Резюме преимуществ
- Применимая сцена
- 1. Используйте метод Handle и thread’s sleep (long)
- 2. Использование метода postDelayed обработчика (Runnable, long)
- 3. Способ совмещения Handler с таймером и TimerTask
- Используйте AlarmManger для достижения долгосрочных задач точного времени
- окончание
- Русские Блоги
- Все, что разработчикам нужно знать о новых разрешениях времени выполнения Android M
Русские Блоги
Несколько способов реализовать таймеры в Android
предисловие
В эти дни я просматриваю официальную документацию по разработке под Android, и есть много предложений по разработке, о которых стоит подумать, и друзья, у которых есть время, могут это проверить. Очень удобно).
Один из курсов упоминал AlarmManager. Этот класс был просто для того, чтобы понять, что это менеджер будильника. Если вы хотите сделать какое-то программное обеспечение, которое лучше, чем напоминания и будильники, вам нужно его использовать. Официальный пример используется для реализации таймера. Я внезапно почувствовал, что это очень волшебная вещь. Я собрал некоторую информацию и записал несколько известных мне способов реализации таймера, чтобы углубить свою память и поделиться ею со всеми.
Механизм сообщений Android
Давайте сначала разберемся с механизмом обработки сообщений Android
То есть механизм работы Handlerd. Для работы обработчика требуется поддержка базовых MessageQueue и Looper. MessageQueue (очередь сообщений), которая хранит некоторые сообщения внутри и обеспечивает внешние операции вставки и удаления в виде очереди (фактически хранилище единого списка). Looper (цикл сообщений), взаимодействуйте с MessageQueue для достижения непрерывного постановки в очередь и удаления из очереди сообщений.
Обработчики могут легко переключать задачи в другие потоки для выполнения, чтобы уменьшить нагрузку на основной поток, поэтому обработчики часто используются для обновлений пользовательского интерфейса. Вот только краткий обзор. Соответствующим блоггерам пока настоятельно не рекомендуется ссылаться на следующие блоги:
Android-механизм асинхронной обработки сообщений
Android AsyncTask полностью решен
Конечно, теперь есть лучшие способы обработки сообщений. Понимание обработчиков и Asynctask позволяет лучше понять механизм внутренней обработки сообщений Android.
Рекомендуется:EventBusСильно отделенный, код лаконичен и понятен, те, кто заинтересован, могут использовать его для справки.
текст
Я использую несколько классов для реализации таймеров: Handler, Timer, Thread, AlarmManager.
AlarmManager
AlarmManager — это открытая функция сигнализации системы, и ее использование ничем не отличается от обычных менеджеров.
Выше приведено основное использование таймера: сначала получите менеджер, затем определите флаг, время цикла и pendingIntent, выданные в указанное время.
PendingIntents, которые обычно выпускаются, являются широковещательными сообщениями. Мы настраиваем приемник широковещания, а затем мы можем обрабатывать нашу функциональную логику, получая эту широковещательную рассылку.
Здесь нужно обратить внимание на настройку в отдельном процессе, который определяется android
Резюме преимуществ
1, Время будильника не требует, чтобы программа поддерживала себя, но система поддерживала, делая программу лучше избегать подверженных ошибкам проблем, но также занимая системные ресурсы, уровень занятости процессора.
2. Даже после выхода из программы сама по себе проблем не возникнет, и система автоматически вызовет соответствующий компонент для выполнения определенной логики, когда придет время.
3. Разнообразие времени, включая одно время, время цикла (выполняется в xx, xx, x, x, с понедельника по пятницу, который час каждый день . )
Применимая сцена
Я думаю, что он больше подходит для независимой функциональной логики. Например, если приложению необходимо регулярно получать последние данные с сервера, использование независимой службы будет отделено от основной функции и простое в обслуживании. Ключ — низкое энергопотребление и непростое допускать ошибки.
Handler
Обработчик может помочь нам управлять потоком пользовательского интерфейса в дочернем потоке, например, дочерний поток анализирует данные и уведомляет пользовательский интерфейс об обновлении интерфейса после синтаксического анализа. Он также может реализовывать таймеры самостоятельно.
Каждый раз, когда таймер запускается, Handler.sendEmptyMessage (0), таймер запускается. Способ продолжения цикла и остановки уже написан в комментариях.
Резюме преимуществ
Каждый цикл работает в основном потоке, избегая перемежающегося взаимодействия между дочерним потоком и основным потоком. Я лично чувствую, что он более управляем, чем таймер, и реализация функции также очень проста.
Применимая сцена
Лично я думаю, что более целесообразно обновлять пользовательский интерфейс непрерывно без сложной и трудоемкой обработки. Например, в проигрывателе нам нужно обновлять отображение времени текущего прогресса воспроизведения, но только обновлять текстовое отображение. Использование обработчика является хорошим выбором.
Timer
Таймер — это класс, в котором Android запускает таймер напрямую, и это также мой самый ранний класс инструментов, который может реализовать функцию таймера.
Его использование общеизвестно:
задержка: время задержки от начала таймера.
period: интервал таймера.
Резюме преимуществ
Использование Timer очень просто: TimerTask — это дочерний поток, который удобен для обработки сложной и трудоемкой функциональной логики, часто используется в сочетании с обработчиком.
Применимая сцена
По сравнению с таймером, реализованным самим обработчиком, таймер может выполнять некоторую сложную обработку. Например, ему нужно отсортировать список с большим количеством объектов. Выполнение в TimerTask не блокирует дочерний поток. Он часто используется в сочетании с обработчиком для завершения сложной обработки. После длительной операции обновите интерфейс пользовательского интерфейса через обработчик.
** Специально говоря: для некоторых мобильных телефонов, если вы обновляете поток пользовательского интерфейса непосредственно в TimerTask, он не будет сообщать об ошибке и работает нормально, но вы должны обратить внимание на то, что обновление пользовательского интерфейса должно выполняться в основном потоке, иначе вы знаете об этом при устранении неполадок. И эта вещь потребляет особую мощность, особенно мощность, особенно мощность. Важно сказать три раза, обязательно выключайте ее, когда она не используется, и используйте ее с осторожностью.
**
Thread
Поток реализует таймер, создав дочерний поток в цикле while, и пользовательский интерфейс может быть обновлен через обработчик. Лично я думаю, что Thread и Timer одинаковы, но выглядят по-разному.
Резюме преимуществ
По ощущениям похож на таймер, без особых преимуществ
Применимая сцена
Как и в случае с таймером, если многопоточность не считается хорошей, часто возникают проблемы, и одновременно существует несколько потоков с одной и той же функцией.Самый Android имеет ограничение на число дочерних потоков, а приложение запускает несколько потоков одновременно. Это ужасная вещь, поэтому, как и Таймер, вы должны тщательно обдумать его при использовании.
1. Используйте метод Handle и thread’s sleep (long)
1) Определить класс обработчика для обработки полученного сообщения.
2) Создайте новый класс потока, который реализует интерфейс Runnable, следующим образом:
3) Добавьте следующую инструкцию, где вы должны начать поток:
Анализ: Реализация собственной чистой Java после сна не гарантирует конкуренцию за ресурсы ЦП, что также вызывает проблему точности, которая должна быть> = 10000 во времени.
2. Использование метода postDelayed обработчика (Runnable, long)
1) Определить класс обработчика
2) Запустить и остановить таймер
Анализ: Ну, это выглядит довольно хорошо, и реализация также проста, и не должно быть никаких блокировок во время сна. Обратите внимание на разницу между ожиданием и интервалом.
3. Способ совмещения Handler с таймером и TimerTask
1) Определить таймер, задание таймера и обработчик
2) Инициализировать задачу таймера
3) Запустить и остановить таймер
Кроме того, Timer также может быть реализован с помощью runOnUiThread следующим образом
Анализ: timer.schedule(task, 2000, 3000); Это означает, что он выполняется в первый раз через 2 секунды, а затем каждые 3000 секунд. Таймер не гарантирует точности и не может разбудить процессор, который не подходит для синхронизации фоновых задач.
Используйте AlarmManger для достижения долгосрочных задач точного времени
Существует три распространенных метода AlarmManager:
- set (тип int, long startTime, PendingIntent pi); // один раз
- setExact (тип int, long triggerAtMillis, операция PendingIntent) // Одноразовая точная версия
- setRepeating(int type,long startTime,long intervalTime,PendingIntent
pi); // повторить точно - setInexactRepeating(int type,long startTime,long
intervalTime, PendingIntent pi); // Неточно, уменьшить потребление энергии
type указывает тип тревоги, startTime указывает первое время выполнения тревоги, long intervalTime указывает время интервала, а PendingIntent указывает действие ответа тревоги
Подробное объяснение вышеуказанных параметров
Тип будильника:
- AlarmManager.ELAPSED_REALTIME: остановка после спящего режима, относительное время загрузки
- AlarmManager.ELAPSED_REALTIME_WAKEUP: ЦП по-прежнему может выходить из спящего режима, чтобы продолжать работать относительно времени загрузки
- AlarmManager.RTC: то же, что 1, но время относительно абсолютного времени
- AlarmManager.RTC_WAKEUP: то же, что 2, но время относительно абсолютного времени
- AlarmManager.POWER_OFF_WAKEUP: все еще доступен после выключения относительно абсолютного времени
Абсолютное время: 1 января 1970 года, 0 часов
startTime:
Первое время срабатывания тревоги в миллисекундах, обычно с использованием текущего времени.
- SystemClock.elapsedRealtime (): миллисекунды, прошедшие с момента запуска системы
- System.currentTimeMillis (): 1 января 1970 г. Прошло 0 миллисекунд
intervalTime:Интервал исполнения.
PendingIntent :
PendingIntent используется для описания намерения и его окончательного поведения, здесь оно используется для получения действия по выполнению запланированной задачи.
Подробный справочный перевод:PendingIntent
Используйте AlarmManger + Service + BarocastReceiver для достижения 5 с после операции печати
Запустите запланированные задачи:
Эффект Демо:
В этом примере достигается эффект бесконечного цикла через вызов цикла широковещательного приемника и службы. Конечно, вы также можете использовать setRepeating напрямую для достижения того же эффекта.
Примечание. Не забудьте зарегистрировать службу и получателя рассылки в файле манифеста.
Метод отмены AlarmManager: AlarmManger.cancel ();
Анализ: этот метод может разбудить процессор и даже достичь точного времени, что подходит для взаимодействия со службой для выполнения некоторых долгосрочных действий синхронизации в фоновом режиме.
В этой статье резюмируется: первый метод не рекомендуется. Краткосрочные запланированные задачи рекомендуется выполнять вторым и третьим способами. Долгосрочные или точные задачи можно выполнять в фоновом режиме с помощью Service.
Любые другие вопросы могут быть подняты ниже или напрямую связаныОфициальный документ AlarmService
окончание
Выше приведены несколько методов реализации таймеров, которые я лично использовал, но они являются лишь краткими введениями. В Интернете есть много связанных материалов для более подробного использования. Если есть ошибки, пожалуйста, оставьте комментарий и комментарий. Я надеюсь закончить чтение этого. Эта статья может помочь вам.
Источник
Русские Блоги
Все, что разработчикам нужно знать о новых разрешениях времени выполнения Android M
Перевод иностранной статьи.
Название android M только что было официально выпущено, и скоро выйдет финальная официальная версия! Android постоянно развивается. Недавнее обновление M сильно отличается. Некоторые серьезные изменения, такие как разрешения во время выполнения, будут иметь разрушительные последствия. Удивительно, но сообщество андроидов редко говорит об этом, хотя это очень важно и может вызвать серьезные проблемы в ближайшем будущем. Вот почему я написал этот блог сегодня. Вот все, что вам нужно знать о разрешениях среды выполнения Android, в том числе о том, как реализовать их в коде. Еще не поздно это исправить.
Новые разрешения времени выполнения
Система разрешений Android всегда была основной концепцией безопасности, потому что эти разрешения запрашиваются только один раз во время установки. После установки приложение может получить доступ ко всему в пределах разрешений без ведома пользователя. Не удивительно, что некоторые плохие парни используют этот недостаток, чтобы злонамеренно собирать пользовательские данные, чтобы делать плохие вещи! Команда Android также знает об этом. 7 лет! Система разрешений была наконец переработана. В Android 6.0 Marshmallow приложение не предоставляет разрешение во время установки. Вместо этого приложение должно попросить пользователя предоставить разрешения по одному во время выполнения.
[img]http://dl2.iteye.com/upload/attachment/0115/4224/ea722a3b-8f76-3301-9bf8-9a11ac34c6fe.png[/img]
Обратите внимание, что диалоговое окно запроса прав доступа не будет появляться само по себе. Разработчик должен назвать это сам. Если функция, которую разработчик хочет вызвать, требует определенного разрешения, а пользователь отказывает в авторизации, функция сгенерирует исключение и вызовет сбой программы.
[img]http://dl2.iteye.com/upload/attachment/0115/4228/7e1bf749-b438-33f3-bb6c-dcb27a269a47.png[/img]
Кроме того, пользователь может в любой момент отменить авторизованные разрешения в настройках.
[img]http://dl2.iteye.com/upload/attachment/0115/4230/249e0713-d31c-374b-b162-34dbc86462c0.png[/img]
Возможно, вы почувствовали холод позади себя. , , Если вы разработчик Android, это означает, что нужно полностью изменить логику вашей программы. Вы не можете напрямую вызывать методы, как раньше, вы должны проверять разрешения для каждого места, которое вам нужно, иначе приложение вылетит! Да. Я не могу убедить вас сказать, что это простой вопрос. Хотя это хорошо для пользователей, для разработчиков это кошмар. Мы должны изменить код, иначе это будет потенциальная проблема в краткосрочной и долгосрочной перспективе. Это новое разрешение во время выполнения работает только тогда, когда мы установили targetSdkVersion равным 23 (что означает, что вы прошли тест 23), и, конечно, это также мобильный телефон системы М. Устройства с приложениями до 6.0 по-прежнему используют старую систему разрешений.
Что происходит с уже выпущенными приложениями
Новые разрешения времени выполнения могут вызвать у вас панику. «Привет, приятель! Как хорошо приложение, которое я выпустил три года назад. Если оно будет установлено на Android 6.0, произойдет ли падение моего приложения. » Не паникуйте, расслабьтесь. Команда андроидов не глупа, наверное, учла эту ситуацию. Если targetSdkVersion приложения ниже 23, будет считаться, что приложение не было протестировано с новыми разрешениями 23, и оно продолжит использовать старые правила: пользователь должен принять все разрешения при установке, и приложение получит эти разрешения после установки. !
[img]http://dl2.iteye.com/upload/attachment/0115/4232/f8511b7b-d4fe-3b34-b3d0-c19bdd3b3123.png[/img]
Тогда приложение работает как раньше! Обратите внимание, что пользователь все еще может отменить авторизованную авторизацию в это время! Когда пользователь отменяет авторизацию, система android 6.0 предупредит, но это не мешает пользователю отменить авторизацию.
[img]http://dl2.iteye.com/upload/attachment/0115/4234/ae3f24d3-2a3a-35e1-babd-7257d807e0d0.png[/img]
Проблема опять в том, что ваше приложение вылетает в это время? Благонамеренный мастер также сообщил об этом группе разработчиков Android: когда мы вызываем функцию, для которой требуется разрешение в приложении, у которого targetSdkVersion меньше 23, а разрешение отменяется пользователем, исключение не выдается. Но он ничего не сделает, в результате чего возвращаемое значение функции будет равно нулю или 0.
[img]http://dl2.iteye.com/upload/attachment/0115/4236/2dbb8676-d5c7-3b89-b696-6590673579d6.png[/img]
Не будь счастлив слишком рано. Хотя приложение не выйдет из строя при вызове этой функции, возвращаемое значение null или 0 все же может вызвать сбой. Хорошая новость (по крайней мере, на данный момент) заключается в том, что этот тип отмены разрешений относительно редок, и я считаю, что очень немногие пользователи делают это.
Если они делают это, они на свой страх и риск. Но в долгосрочной перспективе, я считаю, все еще будет большое количество пользователей, которые отключат некоторые разрешения. Недопустимо, чтобы наше приложение не работало на новых устройствах. Как сделать так, чтобы он работал идеально, лучше изменить код для поддержки новейшей системы разрешений, и я предлагаю вам начать немедленно! Код не был успешно изменен на приложение, которое поддерживает последние разрешения времени выполнения. Не устанавливайте targetSdkVersion 23 для освобождения, иначе у вас будут проблемы.
Только после того, как вы проверили его, перейдите на targetSdkVersion 23.
Внимание: теперь вы создаете новый проект в Android Studio, targetSdkVersion будет автоматически установлен на 23. Если вы еще не поддерживали новые разрешения времени выполнения, я предлагаю вам сначала понизить targetSdkVersion до 22
PROTECTION_NORMAL разрешения класса
Когда пользователь устанавливает или обновляет приложение, система предоставляет все разрешения, принадлежащие PROTECTION_NORMAL, запрошенные приложением (тип базовых разрешений, разрешенных во время установки). К таким разрешениям относятся:
Вам нужно просто объявить эти разрешения в AndroidManifest.xml и авторизовать их во время установки. Нет необходимости проверять разрешения каждый раз, когда вы его используете, и пользователь не может отменить вышеуказанную авторизацию.
Пусть ваше приложение поддерживает новые разрешения во время выполнения
Пришло время разрешить нашему приложению поддерживать новую модель разрешений. Начнем с установки compileSdkVersion и targetSdkVersion на 23.
Например, я хочу использовать следующий метод для добавления контактов.
Для приведенного выше кода требуется разрешение WRITE_CONTACTS. Если вы не запрашиваете авторизацию, приложение вылетает Следующим шагом будет добавление разрешений на объявление в AndroidManifest.xml, как и раньше.
На следующем этапе мне нужно написать еще один метод проверки разрешений. Если нет всплывающего диалогового окна с просьбой авторизации пользователя. Затем вы можете создать контакт на следующем шаге. Разрешения сгруппированы, как показано в следующей таблице:
[img]http://dl2.iteye.com/upload/attachment/0115/4242/6c47bef8-617b-361a-ad81-2d9642ad2e03.png[/img]
Если разрешено какое-либо разрешение той же группы, автоматически разрешаются другие разрешения. Например, после авторизации WRITE_CONTACTS в приложении также есть READ_CONTACTS и GET_ACCOUNTS.
Методы, используемые в исходном коде для проверки и запроса разрешений, — это checkSelfPermission и requestPermissions в Activity. Эти методы представлены api23.
Если у вас есть разрешение, будет выполнен insertDummyContact (). В противном случае requestPermissions выполняется, чтобы открыть диалоговое окно авторизации запроса, как показано ниже:
[img]http://dl2.iteye.com/upload/attachment/0115/4244/fe9374f8-4285-3f7d-8d1d-903b19aee48d.png[/img]
Независимо от того, соглашается пользователь или отказывается, onRequestPermissionsResult активности будет вызываться, чтобы уведомить результат (через третий параметр), grantResults, следующим образом:
Вот как работает новая модель разрешений. Код сложный, но к нему можно только привыкнуть. , , Чтобы приложение было совместимо с новой моделью разрешений, вы должны использовать описанный выше аналогичный метод для обработки всех необходимых ситуаций. Если вы хотите разбить стену, сейчас самое время. , ,
Сделка с «Не напоминай мне снова»
Если пользователь отказывает в авторизации. В следующем всплывающем окне у пользователя будет опция «Не напоминать мне снова», чтобы приложение не продолжало запрашивать авторизацию в будущем.
[img]http://dl2.iteye.com/upload/attachment/0115/4248/057cfb30-9744-364a-9cbe-107ffbf1dedd.png[/img]
Если эта опция проверена пользователем перед тем, как отказать в авторизации. В следующий раз, когда вы запросите разрешения для этого разрешения, диалоговое окно не появится, и в результате приложение ничего не сделает.
Это будет очень плохой пользовательский опыт, и пользователь не получит ответ после выполнения операции. С этой ситуацией нужно разобраться правильно. Перед запросом requestPermissions нам нужно проверить, нужно ли показывать запрос разрешения запроса через shouldShowRequestPermissionRationale действия, код выглядит следующим образом:
Когда разрешение запрашивается в первый раз, и пользователь пометил его, чтобы больше не напоминать, отображается диалоговое окно, которое мы написали. В последнем случае onRequestPermissionsResult получит PERMISSION_DENIED, и диалоговое окно системного запроса не будет отображаться.
[img]http://dl2.iteye.com/upload/attachment/0115/4252/6efa316b-96d6-38e6-b260-f29f60a16ba7.png[/img]
Сделай это!
Запросить несколько разрешений одновременно
Конечно, иногда требуется много разрешений, и вы можете использовать вышеуказанный метод для запроса нескольких разрешений одновременно. Не забудьте проверить настройку «Больше не напоминать мне» для каждого разрешения. Модифицированный код:
Если все разрешения разрешены, onRequestPermissionsResult все равно будет вызываться. Я использую hashmap, чтобы код был чистым и легким для чтения.
Условия гибкие, вы устанавливаете сами. В некоторых случаях разрешение нельзя использовать без разрешения, но в других случаях оно может работать, но производительность ограничена. Я не буду комментировать это, вы можете создать его самостоятельно.
Используйте библиотеки совместимости, чтобы сделать код совместимым со старыми версиями
Приведенный выше код прекрасно работает на Android 6.0 и выше, но он не будет работать до 23 API, потому что нет такого метода. Грубый способ проверить версию
Но это слишком сложно. Я предлагаю использовать библиотеку совместимости v4, которая была совместима с этим. Вместо этого используйте этот метод:
[list]
[*] Авторизованная функция ContextCompat.checkSelfPermission () возвращает PERMISSION_GRANTED, в противном случае она возвращает PERMISSION_DENIED, что верно во всех версиях.
[*] ActivityCompat.requestPermissions () Этот метод вызывается в версии, предшествующей M, непосредственно вызывается OnRequestPermissionsResultCallback с правильным PERMISSION_GRANTED или PERMISSION_DENIED.
[*] ActivityCompat.shouldShowRequestPermissionRationale () вызывается в версиях до M и всегда возвращает false.
[/list]
Благодаря этим трем методам пакета v4 он полностью совместим со всеми версиями! Этот метод требует дополнительных параметров, Context или Activity. Больше ничего особенного. Вот код:
Последние два метода, которые мы также можем использовать во Fragment, используя пакет совместимости v13: FragmentCompat.requestPermissions () и FragmentCompat.shouldShowRequestPermissionRationale (). Эффект такой же, как действие.
Упрощенный код со сторонними библиотеками
Приведенный выше код действительно сложен. Чтобы решить эту проблему, появилось много сторонних библиотек, что действительно быстро. Я много пробовал и, наконец, нашел удовлетворительный PermissionsDispatcher от hotchemi.
Он сделал то же самое, что и я, но упростил код. Гибкость и простота расширения, попробуйте. Если вы не удовлетворены, вы можете найти что-нибудь еще.
Если мое приложение все еще открыто и разрешение отозвано, произойдет ли это?
Разрешение можно отозвать в любой момент.
[img]http://dl2.iteye.com/upload/attachment/0115/4254/d1891d04-0ba1-3d27-9140-602fa79a06bb.png[/img]
Что происходит, когда приложение закрывается при его открытии? Я попробовал это и обнаружил, что приложение внезапно завершит работу в это время. Все в приложении было просто и грубо остановлено, потому что прекращено! Это понятно для меня, потому что, если система позволяет продолжать работу (без определенных разрешений), это вызовет Фредди в мой кошмар. Может хуже .
Я полагаю, что у вас есть четкое понимание новой модели разрешений. Я верю, что вы также знаете о серьезности проблемы. Но у тебя нет выбора. Новые разрешения времени выполнения были использованы в Marshmallow. У нас нет отступления. Единственное, что мы можем сделать сейчас, — это убедиться, что приложение адаптируется к новой модели разрешений.
Хорошей новостью является то, что только для нескольких разрешений требуется модель разрешений во время выполнения. Наиболее часто используемые разрешения, такие как доступ к сети, относятся к нормальному разрешению и автоматически разрешаются во время установки.Конечно, вы должны объявить его, и вам не нужно проверять его позже. Поэтому только небольшую часть кода нужно изменить.
Два предложения:
1. Относитесь серьезно к новой модели разрешений
2. Если ваш код не поддерживает новые разрешения, не устанавливайте targetSdkVersion 23. Особенно, когда вы создаете новый проект в Studio, не забудьте изменить его!
Поговорим о модификации кода. Если структура кода плохо спроектирована, вам потребуется болезненный рефакторинг. Каждое приложение должно быть переработано. Как уже упоминалось выше, у нас нет выбора. , , Перечислите все ситуации, когда вам нужно запросить разрешения. Если A авторизован, а B отклонен, что произойдет. бла, бла
Я желаю реконструкции гладко. Перечислите это как главное, что вам нужно сделать, и начните делать это сейчас, чтобы убедиться, что нет проблем, когда M официально выпущен. Надеюсь, эта статья будет вам полезна, удачного кодирования!
Источник