Android studio локальный сервер

Использование сокетов в Android

Создано большое количество приложений как для Android, так и для других ОС, которые взаимодействуют друг с другом с помощью установления соединенией по сети. К таким приложениям относятся, например, мессенджеры социальных сетей WhatsApp, Viber. Как правило, для установления соединения между такими приложениями используются сокеты.

Сокет (socket) — это интерфейс, позволяющий связывать между собой программы различных устройств, находящихся в одной сети. Сокеты бывают двух типов: клиентский (Socket) и серверный (ServerSocket). Главное различие между ними связано с тем, что сервер «открывает» определенный порт на устройстве, «слушает» его и обрабатывает поступающие запросы, а клиент должен подключиться к этому серверу, зная его IP-адрес и порт. В Android сокеты для передачи данных используют по умолчанию протокол TCP/IP, важной особенностью которого является гарантированная доставка пакетов с данными от одного устройства до другого.

Особенности использования сокетов

Что важно знать при использовании сокетов в Android ?

  • соединения сокетов отключаются при переходе устройства в спящий режим;
  • чтобы не «рвать» соединение при наступлении спящего режима в устройстве можно использовать сервис;
  • для использования интернет-сети необходимо Android-приложению предоставить нужные права в манифесте.

Для определения прав в манифесте необходимо в файл AndroidManifest.xml добавить следующую строку :

Теперь android-приложения будет иметь доступ к сети.

Далее в статье рассмотрим пример клиент-серверного сокетного соединения с передачей сообщения. Функции клиента будет выполнять android-приложение. Серверное java-приложение выполним в IDE Eclipse с использованием пакета concurrent. В конце страницы можно скачать оба приложения.

Клиентский android-сокет

Интерфейс andriod-приложения представлен на следующем скриншоте. Форма приложения включает поле ввода текстового сообщения и кнопки установления соединения сервером, передачи сообщения и закрытия соединения.

Клиентское приложение создадим из двух классов : класс взаимодействия с серверным сокетом Connection и класс стандартной активности MainActivity.

Класс Connection

Класс взаимодействия с сервером Connection получает при создании (через конструктор) параметры подключения : host и port. Методы Connection вызываются из активности и выполняют следующие функции :

Метод Описание
openConnection Метод открытия сокета/соединения. Если сокет открыт, то он сначала закрывается.
closeConnection Метод закрытия сокета
sendData Метод отправки сообщения из активности.
finalize Метод освобождения ресурсов

Листинг Connection

Класс активности MainActivity

В активности MainActivity определены параметры сервера : host, port. Помните, что IP-адрес сервера для Вашего android-примера не может быть localhost (127.0.0.1), иначе Вы будете пытаться связаться с сервером внутри Andriod-системы. Кнопки интерфейса связаны с методами обращения к классу Connection. Кнопки отправки сообщения mBtnSend и закрытия соединения mBtnClose с сервером блокируются при старте приложения. После установления соединения с сервером доступ к кнопкам открывается.

Листинг активности

Методы управления сокетным соединением

Ниже представлены методы обработки событий, связанных с нажатием кнопок интерфейса. Обратите внимание, что подключение к серверу выполняется в отдельном потоке, а открытие доступа к кнопкам в основном потоке, для чего вызывается метод runOnUiThread. Для отправки сообщения серверу также создается отдельный поток.

Читайте также:  Android устройство не сертифицировано

Серверное приложение

Серверное приложение включает 2 класса : Server и ConnectionWorker. Серверный класс Server будет выполнять обработку взаимодействия с клиентом с использованием ConnectionWorker в отдельном потоке. Конструктор ConnectionWorker в качестве параметра получает объект типа Socket для чтения сообщений клиента из потока сокета.

Листинг ConnectionWorker

ConnectionWorker получает входной поток inputStream из клиентского сокета и читает сообщение. Если сообщение отсутствует, т.е. количество прочитанных байт равно -1, то это значит, что соединение разорвано, то клиентский сокет закрывается. При закрытии клиентского соединения входной поток сокета также закрывается.

Серверный класс

Серверный класс Server создадим с использованием многопоточного пакета util.concurrent. На странице описания сетевого пакета java.net и серверного ServerSocket был приведен пример серверного модуля с использованием обычного потока Thread, при работе с которым необходимо решать задачу его остановки : cтарый метод Thread.stop объявлен Deprecated и предан строжайшей анафеме, а безопасная инструкция Thread.interrupt безопасна, к сожалению, потому, что ровным счетом ничего не делает (отправляет сообщение потоку : «Пожалуйста, остановись»). Услышит ли данный призыв поток остается под вопросом – все зависит от разаработчика.

Чтобы иметь возможность остановить сервер «снаружи» в серверный класс Server включим 2 внутренних реализующих интерфейс Callable класса : CallableDelay и CallableServer. Класс CallableDelay будет функционировать определенное время, по истечении которого завершит свою работу и остановит 2-ой серверный поток взаимодействия с клиентами. В данном примере CallableDelay используется только для демонстрации остановки потока, организуемого пакетом util.concurrent.

Листинг CallableDelay

CallableDelay организует цикл с задержками. После завершения последнего цикла cycle поток завершает цикл, останавливает вторую задачу futureTask[1] и закрывает сокет. В консоль выводится соответствующее сообщение.

Листинг CallableServer

Конструктор CallableServer в качестве параметров получает значение открываемого порта для подключения клиентов. При старте (метод call) создается серверный сокет ServerSocket и поток переходит в режим ожидания соединения с клиентом. Остановить поток можно вызовом метода stopTask, либо завершением «задачи» типа FutureTask с данным потоком.

При подключении клиента метод serverSoket.accept возвращает сокет, который используется для создания объекта ConnectionWorker и его запуска в отдельном потоке. А сервер (поток) переходит к ожиданию следующего подключения.

В случае закрытия сокета (завершение внешней задачи FutureTask с данным потоком) будет вызвано исключение Exception, где выполняется проверка закрытия сокета; при положительном ответе основной цикл прерывается и поток завершает свою работу.

Листинг серверного класса Server

Cерверный класс Server создает два потоковых объекта (callable1, callable2), формирует из них две задачи futureTask и запускает задачи на выполнение методом execute исполнителя executor. После этого контролируется завершение выполнение обоих задач методом isTasksDone. При завершении выполнения обеих задач завершается также и цикл работы executor’а.

Два внутренних описанных выше класса (CallableDelay, CallableServer) не включены в листинг.

Источник

Простой клиент-сервер на Android (интернет-мессенджер)

Важно. Все написанное ниже не представляет собой какой либо ценности для профессионалов, но может служит полезным примером для начинающих Android разработчиков! В коде старался все действия комментировать и логировать.

Читайте также:  Ntfs android размер кластера

Поехали. Многие мобильные приложения (и не только) используют архитектуру клиент-сервер. Общая схема, думаю, понятна.

Уделим внимание каждому элементу и отметим:

  • сервер — представляет собой некую программу, работающую на удаленном компьютере, и реализующую функционал «общения» с приложениями-клиентами (слушает запросы, распознает переданные параметры и значения, корректно отвечает на них);
  • клиент — в нашем случае, программа на мобильном устройстве, которая умеет формировать понятный серверу запрос и читать полученный ответ;
  • интерфейс взаимодействия — некий формат и способ передачи/получения запросов/ответов обеими сторонами.

Неважно, как реализован любой из этих элементов, все они в любом случае присутствуют. Давайте реализуем примитивный сервер и Android клиент, работающий с ним. Как пример, будем использовать любой популярный мобильный интернет-мессенджер (Viber, ICQ), а приложение условно назовем «интернет-чат».

Схема взаимодействия следующая:

Клиент, установленный на устройстве А, посылает сообщение для клиента, установленного на устройстве Б. И наоборот. Сервер играет роль связующего звена между устройством А и Б… С, Д… и т.д. Также он играет роль «накопителя» сообщений, для их восстановления, на случай удаления на одном из клиентских устройств.

Для хранения сообщений используем SQL БД как на сервере, так и на устройствах-клиентах (в принципе, вся работа клиентов интернет-мессенджеров и сводится к постоянной синхронизации локальной и удаленной БД с сообщениями). Дополнительно, наш интернет-чат будет уметь стартовать вместе с запуском устройства и работать в фоне. Взаимодействие будет происходить путем HTTP запросов и JSON ответов.

Более логично, если синхронизация происходит через порт/сокет, это с одной стороны упрощает задачу (не нужно циклично слать HTTP запросы на проверку новых сообщений, достаточно проверять состояние прослушиваемого сокета), но с другой стороны, это усложняет создание серверной части приложения.

Делаем сервер

Для реализации «сервера», нам нужно зарегистрироваться на любом хостинге, который дает возможность работы с SQL и PHP.

Создаем пустую SQL БД, в ней создаем таблицу.

  1. author — автор сообщения;
  2. client — получатель сообщения;
  3. data — время и дата получения сообщения на сервере;
  4. 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 из локальной БД.

Читайте также:  Тв приставка android smart phone beeline что это

Отправка нового сообщения из ChatActivity.java происходит сразу на сервер, минуя FoneService.java. При этом наше сообщение НЕ записывается в локальную БД! Там оно появится только после получения его назад в виде ответа сервера. Такую реализацию я использовал в связи с важным нюансом работы любого интернет-чата — обязательной группировкой сообщений по времени. Если не использовать группировку по времени, будет нарушена последовательность сообщений. Учитывая, что клиентские приложения просто физически не могут быть синхронизированы с точностью до миллисекунд, а возможно будут работать даже в разных часовых поясах, логичнее всего будет использовать время сервера. Так мы и делаем.

Создавая новое сообщение, мы передаем запросом на сервер: имя автора сообщения, имя получателя сообщения, текст сообщения. Получая эту запись назад, в виде ответа сервера, мы получаем то, что отправляли + четвертый параметр: время получения сообщения сервером.

Источник

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

  1. 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.

Источник

Оцените статью