- Делаем простейший сборщик ошибок для Android
- How to Fix “android.os.Network On Main Thread Exception error” in Android Studio?
- Solutions
- Solution 1
- Solution 2
- Solution 3
- Solution 4
- ERROR: Exception on thread Thread[main,5,main] #445
- Comments
- DamianWalkerStrauss commented Mar 7, 2019 •
- DamianWalkerStrauss commented Mar 7, 2019
- ImAlipay commented Apr 1, 2019
- labohkip81 commented Jul 19, 2019
- jimmyalvarezcalderon commented Sep 13, 2019
- rom1v commented Sep 13, 2019
- drbeco commented May 3, 2020
- Error handling on Android part 1: how exceptions work for JVM and Android apps
- Error handling on Android
- How do exceptions work for JVM and Android apps?
- What is an Exception object?
- Anatomy of the Throwable class
- Exception handling hierarchy
- Would you like to know more?
- Как исправить android.os.NetworkOnMainThreadException?
- Подход IntentService
- Резюме реализации
Делаем простейший сборщик ошибок для Android
При разработке приложения неизбежно приходится сталкиваться с ошибками в коде и/или окружении. И очень печально когда подобные ошибки встречаются не на тестовом телефоне/эмуляторе а у живых пользователей. Еще печальнее если это не ваш друг бета-тестер и толком никто не может объяснить что и где свалилось.
Обычно при внезапном падении приложения Android предлагает отправить отчет об ошибке, где будет и подробный стэк-трейс и информация о версии вашего приложения. К сожалению пользователи не всегда нажимают кнопку «отправить отчет» а для дебаг-приложений или приложений не из маркета такая функциональность и вовсе недоступна.
Что же делать? На помощь приедет возможность языка Java обрабатывать исключения (Exceptions), в том числе и непойманные (unhandled).
Класс Thread имеет статический метод setDefaultUncaughtExceptionHandler. Данный метод позволяет установить собственный класс-обработчик непойманных исключений. Класс-обработчик должен имплементировать интерфейс Thread.UncaughtExceptionHandler. Каркас обработчика может выглядеть примерно так:
Единственный метод принимает на вход Thread — поток, в котором произошло исключение, и Throwable — само исключение. Приведенная выше реализация просто выводит в лог сообщение без каких либо деталей… Попробуем воспользоваться…
После запуска вышеприведенного кода мы (ура!) получим сообщение в логе… и черный экран. Установив наш собственный обработчик мы удалил штатный обработчик ОС Android и теперь нам больше не предлагают закрыть приложение.
Теперь мы видим и сообщение в логе, и привычное системное сообщение.
Неудобно устанавливать обработчик в Activity. Хоть он и будет установлен а все потоки, но Activity может быть несколько и несколько же стартовых. А еще могут быть сервисы… В этом случае лучше всего устанавливать обработчик при инициализации приложения. Примерно вот так:
При этом нужно не забыть прописать новый класс приложения в манифест. Примерно вот так:
Теперь при старте приложения (не важно какого его компонента) будет установлен обработчик исключений.
Конечно выводить сообщение в лог это не серьезно. Нужно собирать больше информации. Какая версия приложения? Какое исключение не обработано? Какое другое исключение привело к выбросу фатального? В каком потоке? Какой был стэк? Всю эту информацию можно получить. Код простейшего обработчика исключений получающий и сохраняющий на SD-карту всю вышеуказанную информацию размещен на GitHub.
Приведенная реализация сохраняет информацию об необработанном исключении в файл на SD-карте в папку /Android/data/your.app.package.name/files/ (так велит Dev Guide) в файлах вида stacktrace-dd-MM-yy.txt. Для работы в манифесте приложения требуется разрешение WRITE_EXTERNAL_STORAGE.
Естественно это не единственное подобное решение.
Flurry — аналитика для мобильных приложений, содержит свой обработчик ошибок. ACRA — библиотека для Android, собирает данные об ошибках и постит их на GoogleDocs. Android-remote-stacktrace — аналогичная библиотека, шлет данные на пользовательский скрипт-приемник. Также много полезного можно получить в этом вопросе на StackOverflow
Источник
How to Fix “android.os.Network On Main Thread Exception error” in Android Studio?
The main reason for Network On Main Thread Exception Error is because the newer versions of android are very strict against the UI thread abuse. Whenever we open an app, a new “main” thread is created which helps applications interact with the running components of an app’s UI and is responsible for dispatching events to assigned widgets. The entire User Interface is blocked when time-consuming actions are performed on the UI thread.
When an app attempts to perform networking operations on the main thread a Network On Main Thread Exception Error is thrown. The error shows on all applications targeting Honeycomb SDK or higher. Applications get disabled to download files, connect to remote MySQL database, perform HTTP requests or establish a socket connection.
Solutions
The solution is to completely wrap any task that attempts to perform actions like download files, connect to remote MySQL database, perform HTTP requests or establish a socket connection into a separate async function. A new thread is created by the async function, and hence, these processes do not run on the UI thread. We can also override the instruction, but in this situation, the task manager may have to kill the application and it will make the application unresponsive.
Solution 1
To overcome this situation, add the following to the class where the user is performing network operations:
Add the following permissions to the manifest.xml file:
Solution 2
To solve this problem we will use a new Thread
Example:
Solution 3
- Do not use strictMode (only in debug mode)
- Do not change the SDK version
- Do not use a separate thread
Solution 4
When an app attempts to perform networking operations on the main thread a Network On Main Thread Exception Error is thrown.
Источник
ERROR: Exception on thread Thread[main,5,main] #445
Comments
DamianWalkerStrauss commented Mar 7, 2019 •
I have this message and then nothing happens.
I’m running v1.7 both 32 and 64 bits.
I’m using Android 8.1
The text was updated successfully, but these errors were encountered:
DamianWalkerStrauss commented Mar 7, 2019
OK, Solved, don’t worry.
Just went in the CMD to the folder where scrcpy is unziped, then use this:
scrcpy -m 1080
and it works.
ImAlipay commented Apr 1, 2019
very good!it works
labohkip81 commented Jul 19, 2019
Thanks much you saved on me. It works perfect.
jimmyalvarezcalderon commented Sep 13, 2019
Why it happened?
rom1v commented Sep 13, 2019
drbeco commented May 3, 2020
Thanks to @DamianWalkerStrauss ‘s answer, I was able to make this last error of a series of errors go away.
IMHO this issue should not be closed just based on the readme note, since when we google we end up here.
The server error is not clear.
This doesn’t give much clues and we end up googling the error and reading the answer here.
Maybe a simple message like:
Just that would prevent a lot of frustration.
Thanks for this great software. Really enjoy it now after days of builds and apts and snaps and deb packages until I got it working.
Источник
Error handling on Android part 1: how exceptions work for JVM and Android apps
Error handling on Android
How many times have you been in the middle of using a new shiny app, only to have it crash on you?
This is the first in a series of posts that will investigate how the exception handling mechanism works in Java and Android, and how crash reporting SDKs can capture diagnostic information, so that you’re not flying blind in production.
How do exceptions work for JVM and Android apps?
Exceptions should be thrown in exceptional circumstances where the calling code needs to decide how to recover from an error condition.
What is an Exception object?
A [CODE]Throwable[/CODE] is a special type of object which can be thrown and alter the execution path of a JVM application. For example, the code snippet below throws an [CODE]IllegalStateException[/CODE]:
— CODE language-kotlin —
fun main() <
В В В try <
В В В В В В В throw IllegalStateException()
В В В В В В В println(«Hello World»)
В В В > catch (exc: Throwable) <
В В В В В В В println(«Something went wrong»)
В В В >
>
Throwing an exception means that the execution flow changes, and ‘Hello World’ is never printed. Instead, the program counter will jump to the nearest catch block, and executes the error recovery code within, meaning our program prints вЂSomething went wrong’ instead.
Of course, it doesn’t always make sense to recover from a failure — for example, if an [CODE]OutOfMemoryError[/CODE] is thrown by the JVM, there is very little prospect of ever recovering from this condition. In this case it makes sense to leave the [CODE]Throwable as unhandled[/CODE], and allow the process to terminate so the user can restart the app from a fresh state.
Anatomy of the Throwable class
[CODE]Throwable[/CODE] has two direct subclasses: [CODE]Exception[/CODE], and [CODE]Error[/CODE]. Typically an [CODE]Error[/CODE] is thrown in conditions where recovery is not possible, and an [CODE]Exception[/CODE] where recovery is possible. Additionally, there are many subclasses of [CODE]Exception[/CODE] which convey additional meaning — for example, an [CODE]IllegalArgumentException[/CODE] would indicate the programmer passed an invalid argument, and an [CODE]IllegalStateException[/CODE] would indicate that the program encountered an unanticipated state.
— CODE language-kotlin —
fun main() <
В В В try <
В В В В В В В throw IllegalStateException(«This should never happen!»)
В В В В В В В println(«Hello World»)
В В В > catch (exc: Throwable) <
В В В В В В В println(«Something went wrong»)
В В В >
>
Let’s consider the above snippet again. The constructed [CODE]IllegalStateException[/CODE] object captures a snapshot of the application at the time of the error condition:
— CODE language-kotlin —
java.lang.IllegalStateException: This should never happen!
at com.example.myapplication.Exceptions101Kt.foo(Exceptions101.kt:12)
at com.example.myapplication.Exceptions101Kt.main(Exceptions101.kt:5)
at com.example.myapplication.Exceptions101Kt.main(Exceptions101.kt)
This is commonly called a stacktrace. Each line represents a single frame in the application’s call stack at the time of the error, which match the filename, method name, and line number of our original code snippet.
A stacktrace can also contain other useful information, such as program state, which in this case is a static error message, but we could equally pass in arbitrary variables.
Exception handling hierarchy
After throwing an exception, an exception handler must be found to handle the exception, or the app will terminate. In the JVM, this is a well-defined hierarchy, which we’ll run through here.
First up in the exception handling hierarchy is a catch block:
— CODE language-kotlin —
try <
В В В crashyCode()
> catch (exc: IllegalStateException) <
В В В // handle throwables of type IllegalStateException
>
If a catch block isn’t available in the current stack frame, but is defined further down the call stack, then the exception will be handled there.
Next in the hierarchy is implementations of [CODE]UncaughtExceptionHandler[/CODE]. This interface contains a single method which is invoked whenever a [CODE]Throwable[/CODE] is thrown, after the handler has been set:
— CODE language-kotlin —
val currentThread = Thread.currentThread()
currentThread.setUncaughtExceptionHandler < thread, exc ->
В В В // handle all uncaught JVM exceptions in the current Thread
>
It’s possible to set an [CODE]UncaughtExceptionHandler[/CODE] in a few different places; the JVM has a defined hierarchy for these. First, if a handler has been set on the current [CODE]Thread[/CODE], this will be invoked. Next up will be a handler on the [CODE]ThreadGroup[/CODE], before finally, the default handler is invoked, which will handle all uncaught JVM exceptions by printing a stacktrace, and then terminating the app.
— CODE language-kotlin —
Thread.setDefaultUncaughtExceptionHandler < thread, exc ->
В В В // handle all uncaught JVM exceptions
>
It’s the default [CODE]UncaughtExceptionHandler[/CODE] that is most interesting from an error reporting point-of-view, and it’s the default [CODE]UncaughtExceptionHandler[/CODE] that is responsible for showing that all too familiar crash dialog on Android.
The [CODE]UncaughtExceptionHandler[/CODE] interface is the building block of all crash reporting SDKs on the JVM, such as bugsnag-android or bugsnag-java. Read on in part two to learn how we can define a custom handler for uncaught exceptions, and use it to create a crash reporting SDK.
Would you like to know more?
Hopefully this has helped you learn a bit more about Error Handling on Android. If you have any questions or feedback, please feel free to get in touch.
Источник
Как исправить android.os.NetworkOnMainThreadException?
У меня возникла ошибка при запуске моего проекта Android для RssReader.
И это показывает ошибку ниже:
Как я могу исправить эту проблему?
Это исключение возникает, когда приложение пытается выполнить сетевую операцию в своем основном потоке. Запустите свой код в AsyncTask :
Как выполнить задачу:
В файле MainActivity.java вы можете добавить эту строку в свой oncreate()
Не забудьте добавить это в файл AndroidManifest.xml :
Вы должны почти всегда запускать сетевые операции в потоке или как асинхронную задачу. Но если вы знаете лучше и готовы принять последствия и должны выполнять сетевые операции в основном потоке, вы можете переопределить поведение по умолчанию:
ADD это разрешение в файле android manifest.xml:
Ваше приложение (в местах пятнистого интернет-соединения) перестает отвечать на запросы и блокируется, пользователь воспринимает медленность и должен убить силы, и вы рискуете, что менеджер активности убил ваше приложение и сказал пользователю, что приложение остановлено.
У Android есть несколько хороших советов о хороших практиках программирования для разработки для реагирования: http://developer.android.com/reference/android/os/NetworkOnMainThreadException.html
Я решил эту проблему, используя новую Thread .
Вы не можете выполнять сетевой ввод-вывод в потоке пользовательского интерфейса на Honeycomb . Технически это возможно на более ранних версиях Android, но это действительно плохая идея, так как это приведет к тому, что ваше приложение перестанет отвечать на запросы и может привести к тому, что ОС будет убивать ваше приложение за плохое поведение. Вам необходимо запустить фоновый процесс или использовать AsyncTask для выполнения сетевой транзакции в фоновом потоке.
На сайте разработчика Android есть статья о Painless Threading, которая является хорошим знакомством с этим, и она предоставит вам гораздо более глубокую глубину ответа, чем это может быть реально реализовано здесь.
Принятый ответ имеет некоторые существенные сторонники. Не рекомендуется использовать AsyncTask для взаимодействия, если вы действительно не знаете, что делаете. Некоторые из сторон включают:
- AsyncTask, созданный как нестатические внутренние классы, имеет неявную ссылку на окружающий объект Activity, его контекст и всю иерархию View, созданную этим действием. Эта ссылка запрещает сборку Мусора, пока работа в фоновом режиме AsyncTask не завершится. Если соединение пользователя происходит медленно и / или загрузка велика, эти кратковременные утечки памяти могут стать проблемой – например, если ориентация изменяется несколько раз (и вы не отменяете выполняемые задачи), или пользователь переходит к От деятельности.
- AsyncTask имеет разные характеристики исполнения в зависимости от платформы, на которой он выполняется: до уровня API 4 AsyncTasks выполняется последовательно на одном фоновом потоке; От уровня API 4 до уровня API 10, AsyncTasks выполняется в пуле до 128 потоков; Начиная с уровня API 11, AsyncTask выполняется последовательно на одном фоновом потоке (если вы не используете перегруженный метод executeOnExecutor и не предоставляете альтернативный исполнитель). Код, который отлично работает при серийном запуске ICS, может прерываться при одновременном выполнении на Gingerbread, скажем, если у вас есть непреднамеренные зависимости от порядка выполнения.
Если вы хотите избежать кратковременных утечек памяти, у вас есть хорошо определенные характеристики выполнения на всех платформах и есть основа для создания действительно надежной сетевой обработки, вы можете подумать:
- Используя библиотеку, которая хорошо справляется с этим для вас – в этом вопросе есть хорошее сравнение сетевых библиотек или
- IntentService этого используйте Service или IntentService , возможно, с помощью PendingIntent чтобы вернуть результат через метод ActivityActivityResult.
Подход IntentService
- Больше кода и сложности, чем AsyncTask , хотя и не так сильно, как вы думаете
- Будут очереди запросов и запустить их на один фоновый поток. Вы можете легко контролировать это, заменив IntentService эквивалентной реализацией Service , возможно, как этот .
- Хм, я не могу сейчас думать о других
- Избегает проблемы с кратковременной утечкой памяти
- Если ваша активность перезапускается, когда сетевые операции находятся в полете, она все равно может получить результат загрузки с помощью метода onActivityResult
- Лучшая платформа, чем AsyncTask для создания и повторного использования надежного сетевого кода. Пример: если вам нужно сделать важную загрузку, вы можете сделать это из AsyncTask в Activity , но если пользовательский контекст отключит приложение для совершения телефонного вызова, система может убить приложение до завершения загрузки. Менее вероятность убить приложение с активной Service .
- Если вы используете свою собственную параллельную версию IntentService (например, связанную выше), вы можете контролировать уровень параллелизма через Executor .
Резюме реализации
Вы можете реализовать IntentService для выполнения загрузок на одном фоновом потоке довольно легко.
Шаг 1. Создайте IntentService для выполнения загрузки. Вы можете сказать, что загрузить через Intent extra, и передать ему PendingIntent чтобы использовать для возврата результата в Activity :
Шаг 2. Зарегистрируйте службу в манифесте:
Шаг 3. Вызовите службу из Activity, передав объект PendingResult, который служба будет использовать для возврата результата:
Шаг 4: Обработать результат в onActivityResult:
Здесь доступен проект github, содержащий полный рабочий проект Android-Studio / gradle.
- Не используйте strictMode (только в режиме отладки)
- Не меняйте версию SDK
- Не используйте отдельную нить
Использовать службу или AsyncTask
См. Также вопрос переполнения стека:
Android.os.NetworkOnMainThreadException отправляет электронное письмо с Android
Выполнять сетевые действия в другом потоке
И добавьте это в AndroidManifest.xml
Вы отключите строгий режим, используя следующий код:
Это не рекомендуется : используйте интерфейс AsyncTask .
Полный код для обоих методов
Сетевые операции не могут выполняться в основном потоке. Вам нужно запустить все сетевые задачи на дочернем потоке или реализовать AsyncTask.
Вот как вы запускаете задачу в дочернем потоке:
Поместите свой код внутрь:
Использование аннотаций Android – это вариант. Это позволит вам просто запустить любой метод в фоновом потоке:
Обратите внимание, что, хотя он обеспечивает преимущества простоты и удобочитаемости, он имеет свои недостатки.
Это происходит в Android 3.0 и выше. Начиная с Android 3.0 и выше, они ограничили использование сетевых операций (функций, которые обращаются к Интернету) от запуска в потоке основного потока / пользовательского интерфейса (что возникает из ваших методов create и on resume в действии).
Это должно поощрять использование отдельных потоков для сетевых операций. См. AsyncTask для получения более подробной информации о том, как правильно выполнять сетевые действия.
Вы не должны выполнять какую-то трудоемкую задачу в основном потоке (потоке пользовательского интерфейса), как любая операция в сети, операции ввода-вывода файлов или операции базы данных SQLite. Поэтому для такого рода операций вы должны создать рабочий поток, но проблема в том, что вы не можете напрямую выполнять какую-либо операцию, связанную с пользовательским интерфейсом, из рабочего потока. Для этого вам нужно использовать Handler и передать Message .
Чтобы упростить все эти вещи, Android предоставляет различные способы, такие как AsyncTask , AsyncTaskLoader , CursorLoader или IntentService . Поэтому вы можете использовать любой из них в соответствии с вашими требованиями.
Верхний ответ спекта работает отлично.
Если вы пишете AsyncTask inline и не расширяетесь как класс, и, кроме того, если есть необходимость получить ответ из AsyncTask , можно использовать метод get() как AsyncTask ниже.
Хорошей библиотекой является AsyncHTTPClient .
Это делается только для приложений, ориентированных на SDK Honeycomb или выше. Приложениям, использующим более ранние версии SDK, разрешено создавать сети в своих потоках цикла основного события.
Ошибка – предупреждение SDK!
Для меня это было так:
Устройство, на котором я тестировал свое приложение, было 4.1.2, которое представляет собой версию SDK версии 16!
Убедитесь, что целевая версия совпадает с целевой целевой библиотекой Android. Если вы не знаете, что такое ваша целевая библиотека, щелкните правой кнопкой мыши ваш проект -> Путь сборки -> Android , и он должен быть отмечен галочкой.
Кроме того, как указывали другие, укажите правильные разрешения для доступа к Интернету:
Просто для того, чтобы четко сказать что-то:
Основной поток – это в основном поток пользовательского интерфейса.
Поэтому, говоря, что вы не можете выполнять сетевые операции в основном потоке, вы не можете выполнять сетевые операции в потоке пользовательского интерфейса, а это значит, что вы не можете выполнять сетевые операции в *runOnUiThread(new Runnable() < . >* в каком-то другом потоке , или.
(У меня просто был длинный головокружительный момент, пытаясь понять, почему я получал эту ошибку где-то, кроме моего основного потока. Вот почему, этот поток помог, и, надеюсь, этот комментарий поможет кому-то другому.)
Это исключение возникает из-за любой тяжелой задачи, выполняемой в основном потоке, если эта выполняющая задача занимает слишком много времени .
Чтобы этого избежать, мы можем обрабатывать его с помощью потоков или исполнителей
Говоря простыми словами,
НЕ ДЕЛАЙТЕ СЕТЕВЫЕ РАБОТЫ В РЕЖИМЕ UI
Например, если вы выполняете HTTP-запрос, это сетевое действие.
Решение:
- Вы должны создать новую тему
- Или используйте класс AsyncTask
Путь:
Поместите все свои работы внутри
- run() новый поток
- Или doInBackground() класса AsyncTask.
Но:
Когда вы получаете что-то из ответа сети и хотите показать его на своем представлении (например, сообщение ответа дисплея в TextView), вам нужно вернуться обратно в поток пользовательского интерфейса .
Если вы этого не сделаете, вы получите ViewRootImpl$CalledFromWrongThreadException .
Как?
- При использовании AsyncTask обновите представление из onPostExecute()
- Или вызовите runOnUiThread() и обновите представление внутри метода run() .
Хотя выше есть огромный пул решений, никто не упоминается com.koushikdutta.ion : https://github.com/koush/ion
Он также асинхронен и очень прост в использовании:
Это работает. Просто сделал ответ доктора Луиджи немного проще.
Мы также можем использовать RxJava для перемещения сетевых операций в фоновый поток. И это довольно просто.
Вы можете сделать намного больше материалов с RxJava. Вот некоторые ссылки для RxJava. Не стесняйтесь копаться.
Задача RxJava Async в Android
В Android сетевые операции не могут выполняться в основном потоке. Вы можете использовать Thread, AsyncTask (краткосрочные задачи), Service (долгосрочные задачи) для выполнения сетевых операций.
Доступ к сетевым ресурсам из основного (UI) потока вызывает это исключение. Используйте отдельный поток или AsyncTask для доступа к сетевому ресурсу, чтобы избежать этой проблемы.
Вы также можете решить эту проблему, используя Strict Mode, используя приведенный ниже код. Это также альтернатива решению этой проблемы.
Но лучше всего использовать AsyncTask.
Я решил эту проблему простым способом …
Я добавил после oncreate StrictMode.enableDefaults(); И решил это.
Используйте Service или AsyncTask чтобы решить эту проблему.
Для получения дополнительной информации проверьте это .
Вам не разрешено выполнять сетевые операции в потоке пользовательского интерфейса на Android. Вам нужно будет использовать класс AsyncTask для выполнения связанных с сетью операций, таких как отправка запроса API, загрузка изображения с URL-адреса и т. Д. И использование методов обратного вызова AsyncTask, вы можете получить результат в onPostExecute menthod, и вы попадете в поток пользовательского интерфейса, и вы Может заполнять пользовательский интерфейс данными из веб-службы или что-то в этом роде.
Пример. Предположим, вы хотите загрузить изображение с URL-адреса: https://www.samplewebsite.com/sampleimage.jpg
Решение с использованием AsyncTask: соответственно.
Примечание. Не забудьте добавить разрешение Интернета в файл манифеста Android. Он будет работать как шарм. 🙂
Это исключение возникает, когда приложение пытается выполнить сетевую операцию в своем основном потоке. Если ваша задача заняла более пяти секунд, она приближается к силе.
Источник