Creating a local HTTP server on android
Some month back, I was trying to implement an app feature that allowed users to communicate(send texts and files) via a local HTTP connection, more like the way Xender works.
I searched for a lot of ways to do this, I found a few libraries but they didn’t offer the speed and simplicity I was looking for.
Eventually, after days of trying different libraries, I found Sun’s HttpServer.
This tutorial assumes you have basic knowledge of Kotlin and android development.
Let’s get started!!
The sun packages are not available on gradle so you’d have to include them in your project’s lib folder.
You can download the two jar files here . (Courtesy of @Oluwalekae)
Copy and paste the files as shown in this picture 👈
In your MainActivity.kt
- create a function to format our client’s inputStream to a string.
2. Declare a variable mHttpServer, data type HttpServer, which will be the instance of our server.
3. Create a method startServer, this is where we would start our server.
4. variable ‘rootHandler’ is an HttpHandler instance used to handle a request to the root path.
You can create as many handlers as you want based on the number of endpoints you want to have.
The mHttpServer.createContext() method allows us assign handlers to endpoints/routes.
We can add a messageHandler, in the end, our MainActivity.kt would look like this.
You can do most operations that you’d normally do on any http server, like Setting headers, handling file uploads, etc.
You can access the server from:
1. your browser from your phone’s browser using “http://127.0.0.1:5000”
2. or another device connected to your phone’s hotspot using “http://192.168.43.1:5000”
because is 5000 is our port number from the code.
Sun httpServer is the fastest server library you can get, trust me.
You can read more about the HttpServer here, and here.
Источник
Простой клиент-сервер на Android (интернет-мессенджер)
Важно. Все написанное ниже не представляет собой какой либо ценности для профессионалов, но может служит полезным примером для начинающих Android разработчиков! В коде старался все действия комментировать и логировать.
Поехали. Многие мобильные приложения (и не только) используют архитектуру клиент-сервер. Общая схема, думаю, понятна.
Уделим внимание каждому элементу и отметим:
- сервер — представляет собой некую программу, работающую на удаленном компьютере, и реализующую функционал «общения» с приложениями-клиентами (слушает запросы, распознает переданные параметры и значения, корректно отвечает на них);
- клиент — в нашем случае, программа на мобильном устройстве, которая умеет формировать понятный серверу запрос и читать полученный ответ;
- интерфейс взаимодействия — некий формат и способ передачи/получения запросов/ответов обеими сторонами.
Неважно, как реализован любой из этих элементов, все они в любом случае присутствуют. Давайте реализуем примитивный сервер и Android клиент, работающий с ним. Как пример, будем использовать любой популярный мобильный интернет-мессенджер (Viber, ICQ), а приложение условно назовем «интернет-чат».
Схема взаимодействия следующая:
Клиент, установленный на устройстве А, посылает сообщение для клиента, установленного на устройстве Б. И наоборот. Сервер играет роль связующего звена между устройством А и Б… С, Д… и т.д. Также он играет роль «накопителя» сообщений, для их восстановления, на случай удаления на одном из клиентских устройств.
Для хранения сообщений используем SQL БД как на сервере, так и на устройствах-клиентах (в принципе, вся работа клиентов интернет-мессенджеров и сводится к постоянной синхронизации локальной и удаленной БД с сообщениями). Дополнительно, наш интернет-чат будет уметь стартовать вместе с запуском устройства и работать в фоне. Взаимодействие будет происходить путем HTTP запросов и JSON ответов.
Более логично, если синхронизация происходит через порт/сокет, это с одной стороны упрощает задачу (не нужно циклично слать HTTP запросы на проверку новых сообщений, достаточно проверять состояние прослушиваемого сокета), но с другой стороны, это усложняет создание серверной части приложения.
Делаем сервер
Для реализации «сервера», нам нужно зарегистрироваться на любом хостинге, который дает возможность работы с SQL и PHP.
Создаем пустую SQL БД, в ней создаем таблицу.
- author — автор сообщения;
- client — получатель сообщения;
- data — время и дата получения сообщения на сервере;
- text — сообщение.
В двух следующих файлах необходимо изменить переменные, содержащие данные для доступа к БД, на свои, полученные Вами при регистрации Вашего«сервера».
Структура запросов к api:
- обязательный атрибут action — может быть равен select (сервер ответит списком записей из своей БД), insert (сервер добавить новую запись в свою БД), delete (сервер очистит свою БД)
- если action=insert, нам нужно будет передать дополнительные параметры: author (кто написал сообщение), client (кому адресовано сообщение), text (сообщение)
- action=select может содержать дополнительный параметр data, в этом случае ответ сервера содержит не все сообщения из БД, а только те, у которых время создания позднее переданного
Примеры:
- chat.php?action=delete – удалит все записи на сервере
- chat.php?action=insert&author=Jon&client=Smith&text=Hello — добавит на сервере новую запись: автор Jon, получатель Smith, содержание Hello
- chat.php?action=select&data=151351333 — вернет все записи, полученные после переданного времени в long формате
Клиентская часть
Теперь структура Android приложения:
В фоне работает FoneService.java, который, в отдельном потоке, каждые 15 секунд делает запрос на сервер. Если ответ сервера содержит новые сообщения, FoneService.java записывает их в локальную БД и отправляет сообщение ChatActivity.java о необходимости обновить ListView, с сообщениями. ChatActivity.java (если она в этот момент открыта) получает сообщение и обновляет содержимое ListView из локальной БД.
Отправка нового сообщения из ChatActivity.java происходит сразу на сервер, минуя FoneService.java. При этом наше сообщение НЕ записывается в локальную БД! Там оно появится только после получения его назад в виде ответа сервера. Такую реализацию я использовал в связи с важным нюансом работы любого интернет-чата — обязательной группировкой сообщений по времени. Если не использовать группировку по времени, будет нарушена последовательность сообщений. Учитывая, что клиентские приложения просто физически не могут быть синхронизированы с точностью до миллисекунд, а возможно будут работать даже в разных часовых поясах, логичнее всего будет использовать время сервера. Так мы и делаем.
Создавая новое сообщение, мы передаем запросом на сервер: имя автора сообщения, имя получателя сообщения, текст сообщения. Получая эту запись назад, в виде ответа сервера, мы получаем то, что отправляли + четвертый параметр: время получения сообщения сервером.
Источник
Доступ к localhost: порт из эмулятора Android
Я запускаю веб-сервис на моей локальной машине, на котором работает localhost:54722 .
Я хочу вызвать сервис из приложения, запущенного в эмуляторе Android.
Я читал, что использование 10.0.2.2 в приложении получит доступ к localhost, но, похоже, оно не работает с номером порта. Это говорит HttpResponseException: Bad Request .
Вы можете получить доступ к хост-машине с IP-адресом » 10.0.2.2 «.
Это было разработано таким образом командой Android. Таким образом, ваш веб-сервер может отлично работать на локальном хосте, а из вашего приложения для Android вы можете получить к нему доступ через » http://10.0.2.2: «.
Если ваш эмулятор должен иметь доступ к Интернету через прокси-сервер, вы можете настроить собственный HTTP-прокси с экрана расширенных элементов управления эмулятора. Открыв эмулятор, нажмите « Еще» , а затем « Настройки» и « Прокси» . Отсюда вы можете определить свои собственные настройки прокси HTTP.
Используйте 10.0.2.2 для AVD по умолчанию и 10.0.3.2 для Genymotion
Я столкнулся с той же проблемой при выполнении веб-приложения в IIS Express при выполнении Visual Studio. чтобы исправить это, вам нужно перейти в свойства вашего проекта, затем нажать на вкладку «Отладка» и изменить http: // localhost: [ВАШ ПОРТ] на http://127.0.0.1:[YOUR PORT] и установить URL-адрес андроида на http: / /10.0.2.2:[YOUR PORT]. это сработало для меня.
Если вы используете IIS Express, вам может потребоваться привязать все имена хостов, а не просто `localhost ‘. Проверьте этот хороший ответ:
Скажите IIS Express, чтобы он связывался со всеми IP-адресами и именами хостов. В своем файле .config (обычно% userprofile% \ My Documents \ IISExpress \ config \ applicationhost.config или $ (solutionDir) .vs \ config \ applicationhost.config для Visual Studio 2015) найдите элемент привязки вашего сайта и добавьте
Убедитесь, что вы добавили его в качестве второй привязки, а не модифицировали существующую, или VS просто повторно добавит новый сайт, к которому добавлено также. (1) Также может потребоваться запустить VS как администратор.
Я решил это с помощью установки «Конвейер по Keyoti» в Visual Studio Professional 2015. Конвейер сгенерировал УДАЛЕННЫЙ адрес (ваш IP) с портом (45455), который разрешает внешний запрос. Пример:
Конвейер позволяет тестировать веб-приложения с внешних планшетов и телефонов в сети или с эмуляторов Android (без http://10.0.2.2: )
Шаги в следующей ссылке:
У меня есть веб-сервер, работающий на моем локальном хосте.
Если я открою эмулятор и захочу подключиться к своему локальному хосту, который я использую 192.168.x.x . Это означает, что вы должны использовать свой локальный IP-адрес. Кстати, HttpResponseException (Bad Request) это не значит, что хост недоступен.
Некоторые другие ошибки приводят к этому исключению.
Поскольку 10.0.2.2 это не безопасный домен для Android, вы должны разрешить незащищенные домены в конфигурации вашей сети для API 28+, где не-TLS-соединения по умолчанию запрещены.
Вы можете использовать мои следующие конфигурации:
Создайте новый файл в main / res / xml / network_security_config.xml как:
И укажите это в AndroidManifest.xml
Проблема в том, что эмулятор Android отображается 10.0.2.2 на 127.0.0.1 , а не на localhost . Так что настраивайте свой веб-сервер на сервер, 127.0.0.1:54722 а не на localhost:54722 . Это должно сделать это.
После запуска вашего локального хоста вы попали http://localhost:[port number]/ сюда, вы нашли свой номер порта.
Затем получите свой IP-адрес от команды, откройте команду Windows и введите ipconfig
В моем случае IP был 192.168.10.33 таким, чтобы мой URL был http://192.168.10.33:[port number] /. В Android студия использует этот URL в качестве вашего URL. И после этого установите свой URL и номер порта в ручном прокси для эмулятора.
вам нужно установить URL как 10.0.2.2:portNr
portNr = указанный порт ASP.NET Development Server, на котором запущена моя текущая служба localhost:3229/Service.svc
так что мой URL 10.0.2.2:3229
я решил эту проблему таким образом
Я надеюсь, что это помогает.
«BadRequest» — это ошибка, которая обычно отправляется самим сервером, см. Rfc 2616
Сервер не может понять запрос из-за неправильного синтаксиса. Клиент НЕ ДОЛЖЕН повторять запрос без изменений.
Таким образом, у вас есть рабочее соединение с сервером, но ваш запрос не соответствует форме эксперта. Я не знаю, как вы создаете соединение, какие заголовки включены (если они есть) — но это то, что вы должны проверить.
Если вам нужна дополнительная помощь, объясните, о чем ваш код и что он использует для подключения к серверу, чтобы мы получили общую картину.
Вот вопрос с той же проблемой — ответ состоял в том, что в заголовке не был задан тип содержимого.
Я хотел бы показать вам способ доступа к веб-API IISExpress из моего эмулятора Android. Я использую Visual Studio 2015. И я вызываю эмулятор Android из Android Studio.
Все, что мне нужно сделать, это добавить следующую строку в конфигурацию привязки в моем файле applicationhost.config
Затем я проверяю и использую IP4-адрес для доступа к своему API из эмулятора Android.
Требование: вы должны запустить Visual Studio от имени администратора. Этот пост дает идеальный способ сделать это.
Для более подробной информации, пожалуйста, посетите мой пост на GitHub
Надеюсь это поможет.
Для пользователей Laravel Homestead: если кто-то использует Laravel вместе с hometead, вы можете получить доступ к бэкенду приложения, используя 192.168.10.10 в эмуляторе.
Все еще не работает? Еще одним хорошим решением является использование ngrok https://ngrok.com/
Я использую Windows 10 в качестве своей платформы разработки, доступ к 10.0.2.2:port в моем эмуляторе не работает должным образом, и такой же результат для других решений в этом вопросе.
После нескольких часов копания я обнаружил, что если вы добавите аргумент -writable-system в команду запуска эмулятора, все будет работать.
Вы должны запустить эмулятор через командную строку, как показано ниже:
Затем в эмуляторе вы можете получить доступ к службе API, работающей на хост-компьютере, используя IP-адрес локальной сети и порт привязки:
Надеюсь, что это помогает вам.
Чтобы получить доступ к localhost на Android Emulator
Добавьте интернет-разрешение от AndroidManifest.xml
Добавить android:usesCleartextTraffic=»true» , подробнее здесь :
Запустите указанную ниже команду, чтобы найти IP-адрес вашей системы:
Скопируйте IP-адрес, полученный на этом шаге (A)
Запустите ваше бэкэнд-приложение, к которому вы можете получить доступ в localhost или 127.0.0.1 из вашей системы.
Теперь в Android Studio вы можете заменить URL-адрес, если вы используете в коде, или вы можете использовать IP-адрес, полученный на шаге (A), и попробуйте открыть в веб-браузере, например, http://192.168.0.102:8080/
Не забудьте добавить PORT после IP-адреса, в моем случае приложение работало на порту 8080, поэтому я добавил IP, полученный в (A) с портом 8080
localhost, кажется, работал нормально в моем эмуляторе при запуске, а затем я начал получать исключение для соединения, я использовал 127.0.2.2 из браузера эмулятора, и это работало, и когда я использовал это в моем приложении для Android в эмуляторе, он снова начал показывать проблему отказа в соединении ,
тогда я сделал ifconfig и я использовал IP 192.168.2.2, и он работал отлично
Плохой запрос обычно означает, что формат отправляемых вами данных неверен. Может быть несоответствие отображения данных. Если вы получаете неверный запрос, это означает, что вы можете подключиться к серверу, но запрос отправляется неправильно.
Если кто-то все еще ищет это, вот как это сработало для меня.
Вам необходимо найти IP-адрес вашей машины относительно устройства / эмулятора, к которому вы подключены. Для эмуляторов одним из следующих способов является выполнение следующих шагов;
- Перейдите в окно VM Virtual -> выберите подключенное устройство в списке.
- Выберите Настройки -> Сеть -> Узнать, к какой сети подключено устройство. Для меня это был «VirtualBox Host-Only Ethernet Adapter # 2».
- В виртуальной коробке перейдите в Файлы-> Настройки-> Сеть-> Сети только для хоста и найдите IPv4 для сети, указанной в шаге выше. (При наведении вы получите информацию)
Укажите этот IP для доступа к локальному хосту из эмулятора. Порт такой же, какой вы указали при запуске / публикации ваших сервисов.
Примечание № 1: Убедитесь, что вы позаботились о брандмауэрах и правилах входящего трафика.
Примечание № 2: пожалуйста, проверьте этот IP после перезагрузки вашего компьютера. По какой-то причине, даже если я предоставил «Использовать следующий IP», IP-адрес только для хоста изменился.
Я точно решил проблему, когда сервисный уровень использует Visual Studio IIS Express. Просто укажите 10.0.2.2:port не будет работать. Вместо того, чтобы возиться с IIS Express, как упоминалось в других публикациях, я просто помещаю прокси-сервер перед IIS Express. Например, apache или nginx. Nginx.conf будет выглядеть так
Тогда андроид должен указать на мой IP-адрес как 192.168.xx: 8090
Источник