Не одобряется ли выход из приложения?
Идя дальше, пытаясь освоить Android, я просто прочитал следующее:
Вопрос: есть ли у пользователя выбор убить приложение, если мы не добавим пункт меню, чтобы убить его? Если такой опции не существует, как пользователь закрывает приложение?
Ответ: (Romain Guy): пользователь этого не делает, система обрабатывает это автоматически. Вот для чего нужен жизненный цикл активности (особенно onPause/onStop/onDestroy). Независимо от того, что вы делаете, не ставьте кнопку "выйти" или "выйти" из приложения. Это бесполезно с моделью приложения Android. Это также противоречит принципам работы основных приложений.
Хе-хе, за каждый мой шаг в мире Android я сталкиваюсь с какой-то проблемой =(
По-видимому, вы не можете выйти из приложения в Android (но система Android может очень хорошо полностью уничтожить ваше приложение, когда он захочет). Что с этим? Я начинаю думать, что невозможно написать приложение, которое функционирует как "нормальное приложение" - что пользователь может выйти из приложения, когда он / она решит это сделать. Это не то, на что должна полагаться ОС.
Приложение, которое я пытаюсь создать, не является приложением для Android Market. Это не приложение для "широкого использования" широкой публикой, это бизнес-приложение, которое будет использоваться в очень узкой сфере бизнеса.
Я действительно с нетерпением ждал разработки для платформы Android, поскольку она решает множество проблем, существующих в Windows Mobile и.NET. Тем не менее, прошедшая неделя была для меня своего рода поворотом... Надеюсь, мне не придется отказываться от Android, но сейчас это выглядит не очень хорошо =(
Есть ли способ для меня действительно выйти из приложения?
38 ответов
Это в конечном итоге дойдет до вашего вопроса, но я сначала хочу затронуть ряд вопросов, которые вы поднимаете в своих различных комментариях к различным ответам, уже приведенным на момент написания этой статьи. У меня нет намерения передумать - скорее, это здесь для тех, кто придет читать этот пост в будущем.
Дело в том, что я не могу позволить Android определять, когда мое приложение будет закрыто. это должен быть выбор пользователя.
Миллионы людей совершенно довольны моделью, в которой среда закрывает приложение по мере необходимости. Эти пользователи просто не думают о "прекращении" работы Android-приложения, равно как и о "прекращении" веб-страницы или "прекращении" термостата.
Пользователи iPhone во многом аналогичны, в том смысле, что нажатие кнопки iPhone не обязательно "чувствует", как приложение было закрыто, так как многие приложения iPhone поднимаются с того места, где пользователь остановился, даже если приложение действительно было закрыто (так как только iPhone позволяет одно стороннее приложение за один раз, в настоящее время).
Как я уже говорил выше, в моем приложении происходит много вещей (данные, передаваемые на устройство, списки с задачами, которые всегда должны быть там, и т. Д.).
Я не знаю, что означает "списки с задачами, которые всегда должны быть там", но "данные, передаваемые на устройство" - это приятная выдумка, которая ни в коем случае не должна выполняться какой-либо деятельностью. Использовать запланированное задание (через AlarmManager
) обновить ваши данные для максимальной надежности.
Наши пользователи входят в систему и не могут делать это каждый раз, когда им звонят, и Android решает убить приложение.
Есть много приложений для iPhone и Android, которые занимаются этим. Обычно это происходит потому, что они держат учетные данные для входа в систему, а не заставляют пользователей каждый раз входить в систему вручную.
Например, мы хотим проверять обновления при выходе из приложения
Это ошибка в любой операционной системе. Насколько вы знаете, причина того, что ваше приложение "закрывается", заключается в том, что ОС закрывается, и тогда ваш процесс обновления завершится ошибкой. Как правило, это не очень хорошая вещь. Либо проверяйте обновления при запуске, либо проверяйте обновления полностью асинхронно (например, с помощью запланированной задачи), но не при выходе.
Некоторые комментарии предполагают, что нажатие кнопки "Назад" не убивает приложение вообще (см. Ссылку в моем вопросе выше).
Нажатие кнопки НАЗАД не "убивает приложение". Он завершает действие, которое было на экране, когда пользователь нажал кнопку НАЗАД.
Он должен завершаться только тогда, когда пользователи хотят прекратить его - никогда иным образом. Если вы не можете писать приложения, которые ведут себя так же, как в Android, то я думаю, что Android нельзя использовать для написания реальных приложений =(
Тогда ни один не может веб-приложений. Или WebOS, если я правильно понимаю их модель (у меня еще не было возможности поиграть с ней). Во всех этих случаях пользователи ничего не "прекращают" - они просто уходят. iPhone немного отличается тем, что в настоящее время он позволяет запускать только одну вещь за раз (с несколькими исключениями), и поэтому процесс ухода подразумевает довольно немедленное прекращение работы приложения.
Есть ли способ для меня действительно выйти из приложения?
Как все остальные сказали вам, пользователи (через НАЗАД) или ваш код (через finish()
) может закрыть вашу текущую деятельность. Пользователям, как правило, больше ничего не нужно для правильно написанных приложений, больше, чем им нужна опция "выход" для использования веб-приложений.
По определению нет двух одинаковых сред приложений. Это означает, что вы можете видеть тенденции в окружающей среде по мере появления новых и захоронения других.
Например, существует растущее движение, чтобы попытаться исключить понятие "файл". Большинство веб-приложений не заставляют пользователей думать о файлах. Приложения для iPhone обычно не заставляют пользователей думать о файлах. Приложения Android обычно не заставляют пользователей думать о файлах. И так далее.
Аналогичным образом, существует растущее движение, чтобы попытаться устранить понятие "прекращения" приложения. Большинство веб-приложений не заставляют пользователя выходить из системы, а неявно выходят из системы после определенного периода бездействия. То же самое с Android и, в меньшей степени, iPhone (и, возможно, WebOS).
Это требует большего акцента на разработке приложений, сосредоточении на бизнес-целях и отсутствии привязки к модели реализации, привязанной к предыдущей среде приложений. Разработчики, которым не хватает времени или желания сделать это, будут разочарованы новыми средами, которые нарушают их существующую ментальную модель. Это не вина ни одной из этих сред, равно как и вина горы, по которой вокруг нее текут бури, а не сквозь нее.
Например, в некоторых средах разработки, таких как Hypercard и Smalltalk, приложение и инструменты разработки были объединены в одной установке. Эта концепция не получила широкого распространения за пределами языковых расширений приложений (например, VBA в Excel, Lisp в AutoCAD). Поэтому разработчики, которые придумали ментальные модели, которые предполагали наличие инструментов разработки в самом приложении, должны были либо изменить свою модель, либо ограничить себя средами, в которых их модель была бы верна.
Итак, когда вы пишете:
Наряду с другими грязными вещами, которые я обнаружил, я думаю, что разработка нашего приложения для Android не произойдет.
Похоже, что это будет к лучшему, для вас, прямо сейчас. Точно так же я бы посоветовал вам не пытаться портировать ваше приложение в Интернет, поскольку некоторые из тех же проблем, о которых вы сообщали в Android, вы найдете и в веб-приложениях (например, без "завершения"). Или, наоборот, когда-нибудь, если вы портируете свое приложение на Интернет, вы можете обнаружить, что поток веб-приложений может лучше соответствовать Android, и вы можете вернуться к порту Android в это время.
Я просто хотел бы добавить здесь исправление для будущих читателей этой темы. Этот специфический нюанс долгое время ускользал от моего понимания, поэтому я хочу убедиться, что никто из вас не совершит подобных ошибок:
System.exit()
не убивает ваше приложение, если у вас есть более одного действия в стеке. Что на самом деле происходит, так это то, что процесс уничтожается и сразу же перезапускается с меньшим количествомопераций в стеке. Это также происходит, когда ваше приложение убивается с помощью диалогового окна Force Close или даже когда вы пытаетесь завершить процесс из DDMS. Насколько мне известно, это совершенно недокументированный факт.
Короткий ответ: если вы хотите выйти из приложения, вы должны отслеживать все действия в вашем стеке иfinish()
ВСЕ из них, когда пользователь хочет выйти (и нет, итераций по стеку действий нет, поэтому вы должны сами управлять всем этим). Даже это на самом деле не убивает процесс или любые свисающие ссылки, которые вы можете иметь. Это просто заканчивает деятельность. Кроме того, я не уверен,Process.killProcess(Process.myPid())
работает лучше; Я не проверял это.
Если, с другой стороны, для вас нормально, чтобы в вашем стеке оставались действия, есть еще один метод, который упрощает вам задачу:Activity.moveTaskToBack(true)
будет просто фон вашего процесса и покажет домашний экран.
Длинный ответ включает в себя объяснение философии этого поведения. Философия рождается из ряда предположений:
- Прежде всего, это происходит только тогда, когда ваше приложение находится на переднем плане. Если это в фоновом режиме, процесс будет просто нормально завершен. Однако, если она находится на переднем плане, ОС предполагает, что пользователь хочет продолжать делать то, что он / она делал. (Если вы пытаетесь убить процесс из DDMS, вы должны сначала нажать кнопку "Домой", а затем убить его)
- Это также предполагает, что каждый вид деятельности не зависит от всех других видов деятельности. Это часто верно, например, в том случае, если ваше приложение запускает активность браузера, которая является совершенно отдельной и не была написана вами. Действия браузера могут создаваться или не создаваться для одной и той же задачи в зависимости от ее атрибутов манифеста.
- Предполагается, что каждое из ваших действий является полностью самостоятельным и может быть убито / восстановлено в любой момент. (Мне скорее не нравится это конкретное предположение, так как в моем приложении много операций, в которых используется большой объем кэшированных данных, слишком большой для эффективной сериализации во время
onSaveInstanceState
, но что делать?) Для большинства хорошо написанных приложений для Android это должно быть правдой, поскольку вы никогда не знаете, когда ваше приложение будет убито в фоновом режиме. - Последний фактор - это не предположение, а скорее ограничение ОС:явное уничтожение приложения - это то же самое, что и аварийное завершение работы приложения, и то же самое, что и Android, убивающее приложение для освобождения памяти. Кульминацией этого является наш переворот: поскольку Android не может определить, было ли приложение закрыто, или оно зависло, или оно было убито в фоновом режиме, оно предполагает, что пользователь хочет вернуться с того места, где они остановились, и поэтому ActivityManager перезапускает процесс.
Когда вы думаете об этом, это подходит для платформы. Во-первых, это именно то, что происходит, когда процесс убивается в фоновом режиме, и пользователь возвращается к нему, поэтому его необходимо перезапустить с того места, где он остановился. Во-вторых, это то, что происходит, когда приложение аварийно завершает работу и представляет ужасное диалоговое окно Force Close.
Скажем, я хочу, чтобы мои пользователи могли сделать снимок и загрузить его. Я запускаю Camera Activity из своей деятельности и прошу вернуть изображение. Камера помещается в верхнюю часть моей текущей задачи (а не создается в своей собственной задаче). Если у камеры есть ошибка, и она вылетает, это должно привести к сбою всего приложения? С точки зрения пользователя, только камера вышла из строя, и они должны быть возвращены к предыдущей активности. Так что он просто перезапускает процесс со всеми теми же действиями в стеке, за исключением камеры. Поскольку ваши действия должны быть спроектированы так, чтобы их можно было убить и восстановить одним махом, это не должно быть проблемой. К сожалению, не все приложения могут быть спроектированы таким образом, поэтому это проблема для многих из нас, независимо от того, что говорит вам Romain Guy или кто-либо еще. Итак, нам нужно использовать обходные пути.
Итак, мой заключительный совет:
- Не пытайтесь убить процесс. Либо позвони
finish()
на все мероприятия или позвонитеmoveTaskToBack(true)
, - Если ваш процесс падает или уничтожается, и если вам, как и мне, нужны данные, которые были в памяти и сейчас потеряны, вам нужно вернуться к корневому действию. Для этого нужно позвонить
startActivity()
с намерением, которое содержитIntent.FLAG_ACTIVITY_CLEAR_TOP
флаг. - Если вы хотите убить свое приложение с точки зрения Eclipse DDMS, лучше не быть на переднем плане, либо оно само перезапустится. Сначала вы должны нажать кнопку "Домой", а затем завершить процесс.
Все мои приложения имеют кнопки выхода... и я довольно часто получаю положительные отзывы от пользователей из-за этого. Мне все равно, если платформа была разработана таким образом, чтобы приложения не нуждались в них. Говорить "не кладите их туда" довольно нелепо. Если пользователь хочет выйти... Я предоставляю им доступ именно для этого. Я не думаю, что это снижает эффективность работы Android и кажется хорошей практикой. Я понимаю жизненный цикл... и я заметил, что Android не справляется с этим... и это основной факт.
Перестаньте думать о вашем приложении как о монолитном приложении. Это набор экранов пользовательского интерфейса, с которыми пользователь может взаимодействовать с вашим "приложением" и "функциями", предоставляемыми через сервисы Android.
Не знать, что "делает" ваше загадочное приложение, не так уж важно. Давайте предположим, что он туннелируется в какую-то сверх защищенную корпоративную интрасеть, выполняя некоторый мониторинг или взаимодействие и остается в системе до тех пор, пока пользователь не "выйдет из приложения". Поскольку ваш ИТ-отдел командует им, пользователи должны очень хорошо знать, когда они находятся в или из внутренней сети. Следовательно, ваше мышление важно, чтобы пользователи "уходили".
Это просто Создайте службу, которая помещает текущее уведомление в панель уведомлений, говорящее "Я в интрасети, или я бегу". Пусть эта служба выполнит все функции, которые вам необходимы для вашего приложения. Есть действия, которые связаны с этой службой, чтобы позволить вашим пользователям получать доступ к битам пользовательского интерфейса, которые им нужны для взаимодействия с вашим "приложением". И есть кнопка "Меню Android" -> "Выход" (или выход из системы, или что-то еще), которая указывает службе выйти, а затем закрывает само действие.
Это, по сути, именно то, что вы говорите, что вы хотите. Сделано способом Android. Посмотрите на Google Talk или Google Maps Navigation для примеров такого "выхода" возможного менталитета. Единственное отличие состоит в том, что нажатие кнопки "Назад" из-за вашей активности может привести к тому, что процесс UNIX окажется в ожидании на тот случай, если пользователь захочет восстановить ваше приложение. Это действительно ничем не отличается от современной операционной системы, которая кэширует недавно использованные файлы в памяти. После выхода из программы Windows наиболее вероятные ресурсы, которые ей необходимы, все еще находятся в памяти, ожидая замены другими ресурсами, поскольку они загружаются теперь, когда они больше не нужны. Android это то же самое.
Я действительно не вижу твоей проблемы.
Это интересная и проницательная дискуссия с участием многих экспертов. Я чувствую, что этот пост должен быть зациклен на главном веб-сайте разработки Android, потому что он вращается вокруг одного из основных дизайнов ОС Android.
Я также хотел бы добавить свои два цента здесь.
До сих пор я был впечатлен тем, как Android обрабатывает события жизненного цикла, привнося концепцию веб-опыта в нативные приложения.
Сказав это, я все еще верю, что должна быть кнопка " Выйти". Зачем?... не для меня или Теда или любого из технических гуру здесь, но с единственной целью удовлетворения спроса конечного пользователя.
Хотя я не большой поклонник Windows, но давным-давно они представили концепцию, к которой привыкло большинство конечных пользователей (кнопка X)... "Я хочу прекратить запуск виджета, когда" я "хочу".
Это не означает, что кто-то (ОС, разработчик?) Позаботится об этом по своему усмотрению... это просто означает "где моя красная кнопка X, к которой я привык". Мое действие должно быть аналогичным "завершить вызов нажатием кнопки", "выключить устройство нажатием кнопки" и т. Д. И т. П. - это восприятие. Это само по себе приносит удовлетворение тем, что мои действия действительно достигают своей цели.
Даже если разработчик может подделать это поведение, используя приведенные здесь предложения, восприятие все еще остается, то есть приложение должно полностью перестать функционировать (сейчас) из независимого, доверенного и нейтрального источника (ОС) по требованию конечного пользователя.
Вы можете выйти, нажав кнопку Назад или позвонив finish()
в вашем Activity
, Просто позвони finish()
из MenuItem
если вы хотите явно убить его.
Ромен не говорит, что это невозможно, просто это бессмысленно - пользователям не нужно заботиться о том, чтобы уйти или сохранить свою работу или что-то еще, поскольку жизненный цикл приложения побуждает вас писать умное программное обеспечение, которое автоматически сохраняет и восстанавливает свое состояние, что бы ни случилось.
Тед, то, что ты пытаешься сделать, может быть сделано, возможно, просто не то, как ты думаешь об этом прямо сейчас.
Я предлагаю вам прочитать о деятельности и услугах. Прекратите использовать термин "приложение" и начните ссылаться на компоненты, то есть "Активность", "Сервис". Я думаю, вам просто нужно больше узнать о платформе Android; это изменение мышления от стандартного приложения для ПК. Тот факт, что ни в одном из ваших постов не было слова "Активность" (если не считать цитаты из часто задаваемых вопросов, т.е. не ваших слов), говорит о том, что вам нужно прочитать еще немного.
Эта дискуссия сводится к давнему вопросу о том, знают ли разработчики лучше или пользователь знает лучше. Профессиональные дизайнеры во всех областях человеческого фактора борются с этим каждый день.
Тед подчеркнул, что одним из самых скачиваемых приложений на Маркете является "Убийца приложений". Люди получают немного дополнительного серотонина, когда они выходят из приложений. Они привыкли к этому с настольным компьютером / ноутбуком. Это заставляет вещи двигаться быстро. Это держит процессор прохладным и вентилятор от включения. Он использует меньше энергии.
Если вы считаете, что мобильное устройство гораздо меньше, то вы особенно можете оценить их стимул "выбросить за борт то, что вам больше не нужно". Теперь разработчики Android считают, что ОС знает лучше, а выход из приложения - это антиквариат. Я искренне поддерживаю это.
Однако я также считаю, что вы не должны расстраивать пользователя, даже если это разочарование вызвано его собственным невежеством. Поэтому я прихожу к выводу, что наличие опции "Выход" - хороший дизайн, даже если это в основном кнопка плацебо, которая не делает ничего, кроме закрытия вида.
Сообщение в блоге " Когда включить кнопку выхода в приложениях Android" (подсказка: никогда) объясняет это гораздо лучше, чем я. Жаль, что каждый разработчик Android уже прочитал это.
Выдержки:
По моему опыту [пользователи] действительно хотят: Однозначный способ гарантировать, что приложение перестанет потреблять ресурсы (батарея, циклы процессора, передача данных и т. Д.).
Многие пользователи считают, что кнопка выхода реализует это требование, и просят добавить его. Разработчики, стремясь порадовать своих пользователей, обязательно добавят один. Вскоре после этого они оба терпят неудачу.
- В большинстве случаев кнопка выхода просто вызывает
Activity.finish()
, Это в точности эквивалентно нажатию кнопки "назад". Именно так. Службы продолжают работать, а опросы продолжаются. Пользователи могут подумать, что они убили приложение, но они этого не сделали, и скоро они будут еще более раздражены.- Поведение при выходе теперь неоднозначно. Должна ли кнопка "Выход" просто закрыть действие, или она также должна остановить все связанные службы, получатели и сигналы тревоги? Что должен сделать Back? Что произойдет, если вместо этого они попадут домой? Что произойдет, если в вашем приложении есть виджет? Должна ли кнопка выхода остановить это обновление тоже?
Решение состоит в том, чтобы заставить кнопку возврата вести себя так, как вы ожидаете от кнопки выхода. А еще лучше, просто прекратите потреблять ресурсы, когда приложение не видно.
Продолжайте и прочитайте полную статью.
Ответ: (Romain Guy): пользователь этого не делает, система обрабатывает это автоматически. Вот для чего нужен жизненный цикл активности (особенно onPause/onStop/onDestroy). Независимо от того, что вы делаете, не ставьте кнопку "выйти" или "выйти" из приложения. Это бесполезно с моделью приложения Android.Это также противоречит принципам работы основных приложений.
1: Полный выход из приложения обычно не обязателен, но не бесполезен. Что делать, если у окон нет выхода? Система будет работать очень медленно, так как память заполнена, и ОС придется угадывать, с какими программами вы работали. Мне все равно, что скажут Ромейн Гай или даже Ларри Пейдж и Сергей Брин - это неоспоримые факты: системы работают медленнее, когда им приходится убивать задачи, чтобы получить память перед запуском нового приложения. Вы просто не можете сказать мне, что не нужно времени, чтобы убить приложение! Даже свет от далеких звезд требует времени... Есть возможность использовать приложение для полного закрытия приложений.
2: В отличие от того, как работают основные приложения? Что это должно означать? Когда я закончила работу с приложением, оно больше не выполняет никакой работы... Оно просто ждет, когда будет убито ОС, когда потребуется ее память.
Таким образом, существует четкое различие между минимизацией и выходом, и ни один из них не подходит для другого. Мы оставляем отвертку в каждом винте? Или ключ в каждой двери? Оставляем ли мы все наши приборы на высоте, пока не сломается выключатель, и нам нужно включить другой прибор? Разве мы оставляем посудомоечную машину полной посуды и вынимаем достаточно только каждый раз, чтобы освободить место для новых грязных? Оставим ли мы все машины на подъездной дороге, пока - о, неважно.
Если пользователь хочет свернуть приложение, лучше всего свести его к минимуму. Если пользователь хочет выйти из приложения, то лучше всего выйти из него.
Нахмурился? Это точка зрения Android - они нахмурились. И многие многие независимые разработчики Android-новичков нахмурились.
Но когда дело доходит до этого, есть хорошее кодирование и плохое кодирование. Есть хорошие модели программных потоков и есть плохие модели программных потоков.
Оставлять программы в памяти, когда пользователь знает, что они сделали с ними, просто нехорошо. Он абсолютно бесполезен и замедляет работу при запуске новых приложений или при запуске приложений, которые выделяют больше памяти.
Это похоже на ваш автомобиль: бывают ситуации, когда вы оставляете его включенным, например, останавливаетесь на стоп-сигнале или, возможно, проезжаете через фаст-фуд, или останавливаетесь у банкомата. Но есть и другие ситуации, когда вы хотите отключить его - например, когда вы добираетесь на работу, или в продуктовый магазин, или даже домой.
Точно так же, если вы играете в игру, и телефон звонит, да. Приостановите игру и продолжайте работать. Но если пользователь какое-то время закончил с игрой, то он обязательно должен выйти.
Кнопка выхода в некоторых приложениях должна быть больше впереди, чем в других. Например, игры или программы, в которых пользователь, вероятно, захочет полностью выйти, должны иметь очевидный выход. Другие программы, такие как, возможно, программы электронной почты, где выход маловероятен (так что он может продолжать проверять электронную почту) - эти программы не должны тратить пространство экрана первичного управления с опцией выхода, но для хорошего потока программ, это должен иметь вариант выхода. Что если кто-то решит, что не хочет, чтобы его почтовая программа пыталась проверить электронную почту, когда он находится в зоне с плохим покрытием, или, возможно, во время разговора по Skype или чего-то еще? Позвольте им выйти из программы электронной почты, если они хотят!
Приостановка и выход - две жизненно важные задачи, и ни одна не выполняет роль другой.
Если вы не можете понять, как сделать ваши данные / соединения (и, следовательно, ваше "приложение") постоянными, то вы не сможете делать то, что вам "нужно", чтобы делать с Android.
Те, кто скачивает эти милые маленькие App Killers, обычно обнаруживают, что они не помогают работать от батареи или использовать память, но мешают ОС эффективно управлять памятью...
http://android-developers.blogspot.com/2010/04/multitasking-android-way.html
Я хотел бы прочитать "Разработка беспроводных приложений для Android", опубликованную Addison-Wesley. Я только заканчиваю это, и это ОЧЕНЬ тщательно.
Похоже, у вас есть некоторые фундаментальные недоразумения платформы Android. Сначала я тоже был немного расстроен жизненным циклом приложений для Android, но после более глубокого понимания я стал по-настоящему наслаждаться этим подходом. Эта книга ответит на все ваши вопросы и многое другое. Это действительно лучший ресурс, который я нашел для новых разработчиков Android.
Кроме того, я думаю, что вам нужно отпустить линейный порт существующего приложения. Для того, чтобы перенести ваше приложение на платформу Android, часть дизайна приложения изменится. Используемый жизненный цикл приложения необходим, поскольку мобильные устройства имеют очень ограниченные ресурсы по сравнению с настольными системами и позволяют устройствам Android запускать несколько приложений упорядоченно и с учетом ресурсов. Проведите более глубокое изучение платформы, и я думаю, вы поймете, что то, что вы хотите сделать, вполне осуществимо. Удачи.
Кстати, я никоим образом не связан с Addison-Wesley или каким-либо лицом или организацией, связанной с этой книгой. Перечитав мой пост, я чувствую, что немного оборвался. Мне просто очень понравилось, и я нашел это чрезвычайно полезным.:)
Я думаю, суть в том, что нет необходимости выходить из приложения, если у вас нет глючного программного обеспечения. Android выходит из приложения, когда пользователь его не использует, а устройству требуется больше памяти. Если у вас есть приложение, которое требует запуска службы в фоновом режиме, вам, вероятно, понадобится способ отключить службу.
Например, Google Listen продолжает воспроизводить подкаст, когда приложение не отображается. Но всегда есть кнопка паузы, чтобы выключить подкаст, когда пользователь закончил с ним. Если я правильно помню, слушай, даже ставит ярлык на панели уведомлений, чтобы ты всегда мог быстро добраться до кнопки паузы. Другим примером является приложение, например, приложение для Twitter, которое постоянно опрашивает службу в Интернете. Эти типы приложений действительно должны позволять пользователю выбирать, как часто опрашивать сервер, или даже опрашивать в фоновом потоке.
Если вам нужен код, который выполняется при выходе, вы можете переопределить onPause(), onStop() или onDestroy() в зависимости от ситуации. http://developer.android.com/reference/android/app/Activity.html
Почти в 99% случаев нет необходимости, чтобы приложение Android брало свой жизненный цикл. В большинстве случаев все сводится к лучшему планированию или более разумному дизайну приложения. Например, лучше создать внутреннюю службу (не экспортированную) для обработки загрузок и т. Д., Либо разработать действия и задачи, связанные с рабочим процессом пользователя.
Но, как говорится, там, где есть воля, есть путь. Android предоставляет - через класс android.os.Process - намного лучший API, чем Java, для управления базовым процессом. И в отличие от Java, он не рассматривает разработчика как придурка, скрывая все это за простым вызовом java.lang.System.exit().
Так как же попросить ваше приложение совершить самоубийство в Android? Ну, трюк прост:
Создайте свой собственный класс приложений Android, унаследовав его от стандартного класса android.app.Application (не забудьте объявить его в файле AndroidManifest.xml).
Переопределите метод onCreate() и сохраните идентификатор процесса, который запустил ваше приложение:
this.pid = android.os.Process.myPid(); // Save for later use.
Теперь, чтобы убить ваше приложение, предоставьте метод kill():
android.os.Process.sendSignal(pid, android.os.Process.SIGNAL_KILL);
Теперь, когда вам нужно, чтобы ваше приложение совершило самоубийство, просто наберите контекст приложения и вызовите свой метод kill!
((MySuicidalApp) context.getApplicationContext()).kill()
Просто помните, что из-за политик управления процессами в Android, в частности связанных со службами, Android может просто перезапустить службу (см. Раздел "Не следует использовать средства убийцы задач на Android").
Когда я создаю приложение в Android, я вижу это так:
- Вы работаете со своим приложением
- Телефон зазвонил
- Вы принимаете звонок
- В конце разговора вы возвращаетесь к своей заявке в том же месте, где были
Для этого вам понадобится только кнопка " Назад" или кнопка " Домой" на вашем телефоне (коротким или долгим нажатием) и панель уведомлений.
При выходе из приложения я использую кнопку " Назад" только до тех пор, пока у меня не закончится или кнопка " Домой".
Я думаю, что так задумано большинство приложений. Но если мне нужен какой-то сеанс или соединение, я дал понять пользователю с помощью кнопки входа / выхода и уведомления (строка заголовка или что-то еще). Это довольно другой стиль, нежели стиль приложения "выход".
На ПК у вас рабочий стол с несколькими графическими интерфейсами, а на Android, очевидно, у вас есть несколько задач, но вы отображаете только одно приложение за раз (я не рассматриваю здесь виджеты ^^). А на мобильном телефоне в любое время вы можете получить уведомление о чем-то более важном, чем то, что вы делаете.
Таким образом, вся концепция приложения основывается на чем-то ином, чем "вход в приложение - работа - выход из приложения".
Хммм...
Я думаю, что вы просто не видите приложение для Android правильно. Вы можете легко сделать что-то вроде того, что хотите:
Сохраняйте / восстанавливайте состояние приложения, как это рекомендуется в документации разработчика.
Если на этапе восстановления требуется какой-либо логин (информация о логине / сеансе недоступна), сделайте это.
В конце концов добавьте кнопку / меню / тайм-аут, в этом случае вы будете делать
finish()
без сохранения имени входа и другой информации о сеансе, неявно завершая сеанс приложения: поэтому, если приложение будет запущено / выведено на передний план, оно начнет новый сеанс.
Таким образом, вам все равно, действительно ли приложение удалено из памяти или нет.
Если вы действительно хотите удалить его из памяти (это не рекомендуется, и, кстати, с какой целью?), Вы можете уничтожить его условно в конце onDestroy()
с java.lang.System.exit(0)
(или возможно restartPackage(..)
?). Конечно, делайте это только в том случае, если вы хотите "действительно завершить приложение", потому что onDestroy()
является частью нормального жизненного цикла деятельности, а не завершением приложения.
Поскольку приложение в контексте Android - это просто набор неопределенно связанных действий, выход из приложения на самом деле не имеет особого смысла. Вы можете завершить () действие, и будет отображено представление предыдущего действия в стеке действий.
Я согласен с Тедом. Я понимаю, что выход из приложения - это не "способ Android", но, похоже, это не следует исключать. Вот три причины, по которым вам может потребоваться реальный выход из приложения (а не только действие):
Пользователь может захотеть контролировать, какое приложение будет убито в случае нехватки памяти. Если важное приложение A работает в фоновом режиме, вы можете выйти из приложения B, когда закончите, чтобы приложение A не было убито операционной системой.
Если в вашем приложении хранятся конфиденциальные данные, кэшированные в памяти, вы можете убить приложение, чтобы приложение для вирусов / червей / мошенников не смогло его найти. Я знаю, что модель безопасности должна предотвращать это, но на всякий случай...
Если ваше приложение использует ресурсы (такие как сеть, процессор, датчики и т. Д.), Которые могут негативно повлиять на телефон, то один из способов обеспечить освобождение этих ресурсов - это выйти из приложения. Я понимаю, что приложения с хорошим поведением должны освобождать ресурсы, когда они не нужны. Но опять же выход из приложения кажется разумным способом убедиться в этом.
Ядро Linux имеет функцию, называемую Убийца нехватки памяти (как упоминалось выше, политики настраиваются на уровне пользовательского пространства, а также ядро не является оптимальным, но ни в коем случае не ненужным).
И это активно используется Android:
Примечания Android (Информация об убийстве OOM - где вы можете настроить функцию OOM на Android)
Некоторые приложения пользовательского пространства доступны, чтобы помочь с этими приложениями уничтожения, например:
Я надеюсь, что со временем все изменится. Пользователь должен иметь возможность убить приложение или процесс, если ОС правильно установила процесс приложения в "песочницу". Существует мнение, что приложения должны быть написаны безупречно, иначе пользователь будет использовать только те приложения, которые соответствуют всем рекомендациям SDK. Я думаю, что это высокий заказ.
Жизненный цикл приложения Android предназначен для пользователей мобильных телефонов, а не пользователей компьютеров.
Жизненный цикл приложения - это крайне упрощенная парадигма, необходимая для превращения сервера Linux в потребительское устройство.
Android - это Java поверх Linux, настоящая кроссплатформенная серверная ОС. Вот как это распространяется так быстро. Жизненный цикл приложения заключает в себе основную реальность ОС.
Для мобильных пользователей приложения просто установлены или не установлены. Нет концепции бега или выхода. Фактически, процессы приложения должны запускаться до тех пор, пока ОС не выпустит их для своих удерживаемых ресурсов.
Поскольку это переполнение стека, любой, кто читает это, является пользователем компьютера и должен отключить 90% своих знаний, чтобы понять жизненный цикл мобильного приложения.
Вы, очевидно, нашли нужный ответ в команде finish(). Это не удалит ваше приложение из памяти, но Android будет делать это всякий раз, когда ему понадобятся ресурсы, поэтому не имеет значения, что вы не будете делать это явно.
Я хотел бы только добавить, что для достижения полного эффекта, который обычно имеет выход из приложения, вы должны сбросить состояние приложения до того состояния, в котором оно обычно находится во время первого запуска после загрузки устройства, незадолго до для вызова финиша () во всех ваших действиях. Таким образом, если пользователь снова выберет ваше приложение, оно будет казаться запущенным "свежим", без какого-либо состояния, оставшегося от точки до симулированного "выхода".
Если есть какие-то специальные действия, которые должны выполняться только при "выходе", такие как сохранение работы пользователя или чего-либо еще, вы также можете выполнить их до повторной инициализации части вышеприведенной процедуры.
Этот подход позволяет вам достичь своей цели, используя команду "выход", не нарушая философию Android, согласно которой управление ресурсами ОС, включая закрытие приложений, остается в руках операционной системы.
Лично я бы не стал использовать этот подход, потому что пользователи Android ожидают, что приложение сохранит свою непрерывность при повторном посещении, и поэтому они не привыкли к модальности "выхода" из приложения. Вместо этого я бы поддерживал "чистую" функцию, которую пользователь может вызывать для сброса приложения до некоторого начального состояния по умолчанию, без необходимости "оставлять" его в процессе.
Единственное исключение - когда пользователь нажимает кнопку "Назад" достаточное количество раз, чтобы приложение закрылось. В этой ситуации пользователь не ожидает, что состояние будет сохранено (и если в приложении есть несохраненное состояние, то вы, как разработчик, должны иметь код, обрабатывающий кнопку "назад", которая обнаруживает эти несохраненные данные, и предлагает пользователю сохранить его в SharedPreferences или в файл, или на другой энергонезависимый носитель).
Относительно system.exit(0):
Если вы решите использовать system.exit (0), чтобы закрыть приложение с грубой окончательностью (например, в результате последнего нажатия кнопки "назад"), то я бы предупредил вас, что, хотя для меня это "работает", а в некоторых Кейсы были единственным способом, которым я смог закрыть приложение, не оставив следов, есть один незначительный сбой, который возникает в Jelly Bean при использовании этого подхода.
В частности, если вы используете список "Недавние приложения", чтобы открыть свое приложение, а затем нажмите кнопку "Назад", чтобы закрыть приложение (с этим закрытием, реализованным с помощью system.exit(0)), список "Недавние приложения" снова станет видимым, так как он будет никогда не был закрыт. Если вы затем нажмете на запись вашего приложения в этом списке, чтобы запустить его во второй раз из того же, уже открытого списка недавних приложений, ответа не будет.
Я подозреваю, что причина этого в том, что в списке "Последние приложения" содержится ссылка на ваше приложение, которое перестало работать из-за того, что вы закрыли приложение с помощью system.exit(0). Более цивилизованное закрытие вашего приложения с использованием finish() могло бы информировать ОС таким образом, чтобы оно могло обновить свой список недавних приложений, но system.exit (0), по-видимому, этого не делает.
Само по себе это не является большой проблемой, так как очень немногие люди откроют приложение из Недавних приложений, затем закроют его, а затем сразу же откроют снова из того же открытого списка Недавних приложений. И если они коснутся кнопки "Домой", а затем снова откроют список "Последние приложения", запись вашего приложения будет там, и она будет полностью функциональной. Но я думаю, что это показывает, что использование system.exit (0) может помешать правильной связи между вашим приложением и ОС, и это предполагает, что могут быть другие, более серьезные, возможно, тонкие последствия использования этого подхода.
Прежде всего, никогда не используйте System.exit(0). Это как заставить человека спать, бить его по голове!
Второе: я сталкиваюсь с этой проблемой. Прежде чем поделиться своим решением, я хочу поделиться своими мыслями.
Я думаю, что "кнопка выхода" глупа. Действительно действительно очень глупо. И я думаю, что пользователи (потребители), которые просят кнопку выхода для вашего приложения, тоже глупы. Они не понимают, как работает ОС и как управляет ресурсами (и она отлично работает).
Я думаю, что если вы напишите хороший кусок кода, который будет делать правильные вещи (обновления, сохранять и отправлять сообщения) в нужный момент и в определенных условиях и с использованием правильных вещей (Service и Receiver), он будет работать довольно хорошо, и никто не будет жаловаться,
Но для этого вы должны изучить и узнать, как все работает на Android. Во всяком случае, это мое решение предоставить пользователям "кнопку выхода".
Я создал меню опций, всегда видимое в каждом действии (у меня есть супер-активность, которая делает это).
Когда пользователь нажимает на эту кнопку, вот что происходит:
Intent intent = new Intent(this, DashBoardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedPreferences settings = getSharedPreferences(getString(PREF_ID), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, true);
// Commit the edits!
editor.commit();
startActivity(intent);
finish();
Поэтому я сохраняю в SharedPreferences то, что хочу убить мое приложение, и запускаю Intent. Пожалуйста, посмотрите на эти флаги; они очистят весь мой backstack, вызывая мою активность DashBoard, которая является моей "домашней" деятельностью.
Итак, в моей Деятельности Dashboard я запускаю этот метод в onResume:
private void checkIfForceKill() {
// CHECK IF I NEED TO KILL THE APP
// Restore preferences
SharedPreferences settings = getSharedPreferences(
getString(MXMSettingHolder.PREF_ID), Context.MODE_PRIVATE);
boolean forceKill = settings.getBoolean(
MusicSinglePaneActivity.FORCE_EXIT_APPLICATION, false);
if (forceKill) {
//CLEAR THE FORCE_EXIT SETTINGS
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean(FORCE_EXIT_APPLICATION, false);
// Commit the edits!
editor.commit();
//HERE STOP ALL YOUR SERVICES
finish();
}
}
И это будет работать довольно хорошо.
Единственное, что я не понимаю, почему это происходит, так это то, что, когда я делаю последний финиш (и я проверил: он отслеживает весь правильный поток onPause → onStop → onDestroy), приложение все еще находится в недавнем действии (но это пусто).
Похоже, что последнее намерение (которое запустило DashboardActivity) все еще находится в системе.
Я должен копать больше, чтобы также удалить его.
Без функции выхода для разработчика приложения, чтобы убить их собственное приложение, это очень плохой дизайн.
Мое приложение должно позволять пользователю динамически изменять данные в динамическом режиме во время выполнения, а пользователь должен перезапустить мое приложение, чтобы изменения вступили в силу, но Android не разрешил моему приложению перезапускаться самостоятельно. Android OS имеет очень плохой дизайн жизненного цикла приложения.
Для закрытия приложения в любой момент используйте FLAG_ACTIVITY_CLEAR_TOP
флаг в намерении, а затем system.exit();
Или есть аналогичный способ, но без system.exit()
когда вы хотите выйти, вызовите этот метод:
public void exit() {
startActivity(new Intent(this, HomeActivity.class).
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | IntentCompat.FLAG_ACTIVITY_CLEAR_TASK).putExtra(EXIT_FLAG, true));
}
В вашем HomeActivity.onCreate()
добавить следующий код
protected void onCreate(Bundle savedInstanceState) {
if (getIntent().getBooleanExtra(EXIT_FLAG, false)) {
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) == 0) {
finish();
}
}
......................
Это будет работать без нарушения жизненного цикла Android.
Существует (относительно) простой дизайн, который позволит вам обойти головоломку "выхода". Сделайте так, чтобы ваше приложение имело "базовое" состояние (активность), которое является просто пустым экраном. В первом onCreate действия вы можете запустить другое действие, в котором находятся основные функциональные возможности вашего приложения. Затем можно завершить "выход", завершив () это второе действие и вернувшись к основанию просто пустого экрана. ОС может хранить этот пустой экран в памяти столько, сколько захочет...
По сути, поскольку вы не можете выйти из ОС, вы просто превращаетесь в самосозданное ничто.
Вы, вероятно, потратили много лет на написание "правильных" программ для "правильных" компьютеров. Вы говорите, что учитесь программировать на Android. Это всего лишь одна из вещей, которую вам нужно усвоить. Вы не можете потратить годы на рисование акварелью и предположить, что картина маслом работает точно так же. Это было наименьшее из тех вещей, которые были для меня новыми концепциями, когда я писал свое первое приложение восемь лет назад.
Каждый раз, когда вы переходите на следующую страницу через намерение, используйте:
`YourActivityname.this.finish()`;
Пример:
Intent intent = new Intent(getApplicationContext(), SMS.class);
startActivity(intent);
MainActivity.this.finish();
Чтобы никакие действия не выполнялись в фоновом режиме, а когда вы хотите выйти из приложения, используйте:
MainActivity.this.finish();
android.os.Process.killProcess(android.os.Process.myPid());
System.exit(0);
getParent().finish();
Этот выход работал для меня как оберег:)
Мне потребовалось больше времени, чтобы прочитать эти вопросы и ответы, чем на самом деле реализовать полу-правильный жизненный цикл приложения Android.
Это приложение GPS, которое опрашивает точки и отправляет текущее местоположение в веб-сервис каждые несколько секунд, используя поток... Это может быть опрос каждые 5 минут в случае Теда для обновления, тогда onStop может просто запустить операцию обновления, которую Тед был так обеспокоен тем, найден ли кто-нибудь (асинхронный Тед, не пишите код, как программист Windows, иначе ваши программы будут работать как программы Windows... например, это не так сложно).
Я сделал некоторый исходный код в onCreate, чтобы настроить вещи на время жизни, в том числе checkUpdate.start();
:
...
@Override
public void onStart() {
super.onStart();
isRemote = true;
checkUpdate.resume();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 0, luh);
}
@Override
public void onPause() {
isRemote = false;
checkUpdate.suspend();
locationManager.removeUpdates(luh);
super.onStop();
}
Этот код может быть совершенно неверным, но он работает. Это одно из моих первых приложений для Android.
Вуаля, приложение, которое не использует ЦП, когда оно находится в фоновом режиме, но мгновенно готово к повторному открытию, потому что оно находится в ОЗУ (хотя не удерживает ОЗУ, как жизненный цикл Android)... приложение всегда готово, это телефон, ребята / девочки. Если приложение должно было использовать всю оперативную память и не могло быть закрыто ОС, то это могло бы перестать звонить =P. Вот почему ОС должна быть в состоянии закрыть ваше приложение, когда оно находится в фоновом режиме (если ваше приложение не работает). не ресурс, он не будет закрыт, кстати, так что давайте просто напишем лучшие приложения.
В любом случае, если вы хотите прекратить свою заявку, вы всегда можете позвонить System.exit(0);
,