Intereting Posts
Как настойчиво сохранять PendingIntent, предоставляемые другим приложением Есть ли какой-либо API Google Now, который позволяет интегрировать наши собственные приложения в настоящее время? Сохраняет ли ViewModel операцию сохранения и восстановления? Любой, кто делает C2DM на Android Почему регистрация IabBroadcastReceiver в действии плохая идея? Защита паролем запуска приложения для Android Ошибка «Вы не должны вызывать setTag () при просмотре. Glide нацеливается на« когда используется Glide Мониторинг памяти, загруженной моим приложением в Android Eclipse вставляет arg0, arg1 и т. Д. Вместо правильных имен параметров при переопределении методов Android Как обновить содержимое вкладки фрагментов при нажатии кнопки Плагин LaunchNavigator Ionic2 не установлен Как декодировать MP3 в Android в приложении? Как указать, какой вид активности запускается при запуске приложения? Расширение ArrayAdapter в Android Какой stretchMode использовать в GridView на android

Есть ли какой-либо механизм обратного вызова в android, когда есть данные, доступные для чтения в сокете

Ну, я знаком с программированием сокетов в среде c, iOS. Но теперь я пытаюсь подключить свой Android и мой удаленный сервер через сокеты … В качестве запуска я написал простую серверную программу на C и запустил ее на своем рабочем столе, Терпеливо ждать запроса на соединение, принимать соединение, затем ждать некоторую строку запроса, а при получении строки запроса возвращает некоторую строку ответа, затем снова ждут следующего запроса и продолжаем. Ну, вы поняли, что ..

Так далеко

  1. Я установил соединение с моим Android и сервером
  2. Отправленные и полученные данные

И это мой клиентский код ..

public class SocketMaster { private Socket clientSocket = null; BufferedReader socketReadStream = null; public boolean connectToHost(String ip, int port){ try { InetAddress serverAddr = InetAddress.getByName(ip); try { clientSocket = new Socket(serverAddr, port); socketReadStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); String line = null; String stringToSend = "This is from client ...Are you there???"; //Write to server..stringToSend is the request string.. this.writeToServer(stringToSend); //Now read the response.. while((line = socketReadStream.readLine()) != null){ Log.d("Message", line); } } catch (IOException e) { e.printStackTrace(); return false; } } catch (UnknownHostException e) { e.printStackTrace(); return false; } return true; } public boolean writeToServer(String stringToSend){ DataOutputStream dos = null; try { dos = new DataOutputStream(clientSocket.getOutputStream()); } catch (IOException e) { e.printStackTrace(); return false; } try { dos.write(stringToSend.getBytes()); } catch (IOException e) { e.printStackTrace(); return false; } return true; } } 

Я создаю объект SocketMaster из другого действия и называет connectToHost, передавая ip и порт сервера. Все работает отлично, и я могу подключать, отправлять и получать данные.

Теперь мой вопрос касается этих строк

 //Now read the response.. while((line = socketReadStream.readLine()) != null){ Log.d("Message", line); } 

Из того, что я понимаю, поток, который выполняет этот код

  • Блоков до тех пор, пока не будут прочитаны данные
  • Если доступны данные, прочитайте его, а затем из-за цикла снова блокируется, пока не появится следующий фрагмент данных

Просто я не могу запустить этот код в основном потоке, так как он заблокирует мои действия в пользовательском интерфейсе. Я могу подумать об использовании этого в фоновом потоке, который является одним из вариантов …

Но в идеале я хочу …

Обратный вызов (я думаю, слушатель в терминах android, любой, кто знаком с iOS CFSocket и обратным вызовом ), метод, который вызывается, когда есть данные, доступные для чтения, чтобы я мог просто читать данные, а затем возвращаться.

Есть ли такой механизм в android / java … Если нет (:-(), может ли кто-нибудь связать меня с некоторым примером, где обработка сокетов выполняется в фоновом режиме …

EDIT: Я сам не спрашивал о создании механизма обратного вызова. Я просто спрашивал, есть ли присутствующий слушатель, который уведомляет вас, когда есть данные для чтения, когда соединение отключилось. Таким образом, я могу исключить вышеупомянутый цикл while. .. Если никакого обратного вызова нет, я готов переместить этот сокет в другой поток, который перемещается вокруг и читает данные (которые я уже сделал) …

**

EDIT Bounty время снова ..

**

Ну, я 2 слабый старый разработчик Android и Java с хорошим 3,5-летним опытом разработки c / c ++ / объектива c за этим … Итак, я видел низкоуровневые родные сокеты (которые блокируются (настраиваются) при использовании read () и Recv ()) и CFSocket яблока (который сам по себе является сосетом C, но предоставляет оболочку для обеспечения механизма обратного вызова). Я не прошу о кодировании механизма обратного вызова здесь (который я искренне готов сделать, если нет готовой альтернативы Настоящее, но зачем снова изобретать колесо?) … Я начинаю понимать java как очень продвинутую и высокоуровневую платформу. Я думал, что там будет какая-то библиотека обертки более высокого уровня, скрывающаяся вокруг. Так что я думаю об увеличении аудитории К этой теме, начав щедрость ..

Solutions Collecting From Web of "Есть ли какой-либо механизм обратного вызова в android, когда есть данные, доступные для чтения в сокете"

В Java нет готового обратного вызова. Вы можете легко реализовать его, используя классы в пакете NIO. Вам в основном нужны Selector и SocketChannel. Если вы знакомы с выбором (2), вам должно быть легко следовать. Если нет, попробуйте учебник NIO.

http://download.oracle.com/javase/1.5.0/docs/api/java/nio/channels/SocketChannel.html http://download.oracle.com/javase/1.5.0/docs/api/java /nio/channels/Selector.html

В любом случае вам нужно будет опросить сокет, чтобы проверить, есть ли данные, и вы не можете сделать это в основном потоке. Если ваше приложение для Android не должно управлять несколькими подключениями в одном и том же потоке, может быть намного проще использовать блокировку ввода-вывода. Еще одна вещь, которую следует учитывать: если это необходимо для непрерывной работы / в течение длительного времени, вам необходимо перенести ее на службу. Даже тогда ОС может убить его, если у него закончится нехватка ресурсов, поэтому будьте готовы к переподключениям.

НТН

Вот что вы можете попробовать:

Определите обработчик в java, как это

 public interface NwkCallback { void handle(int code, Object obj); } 

Теперь определите класс, который обрабатывает сетевые операции:

 public class Nwk { static DefaultHttpClient CLIENT = null; static DefaultHttpClient c() { if (null == CLIENT) { // Create a httpclient } else return CLIENT; } } public static void onReceive(final Object data, final NwkCallback callback) { background(new Runnable() { @Override public void run() { try { // Write to server and wait for a response // Once you receive a response // return result back using // callback.handle(1,whatever_server_returned) } catch (Exception e) { Logger.e(e); } } } }); 

В потоке пользовательского интерфейса или в другом месте используйте метод onReceive as

 Nwk.onReceive(string_passed_to_server, new NwkCallback() { @Override public void handle(final int code, Object obj) { if(code==1) { // Print obj } } }); 

Если вы ищете образец приложения для Android, который использует службу для управления долгосрочными подключениями, проверьте ConnectBot:

http://code.google.com/p/connectbot/source/browse/

Он использует службу для управления терминальными соединениями. Это очень сложный набор кода, однако, возможно, потребуется некоторое копание, чтобы выяснить, какие бит вы хотите использовать.

Большинство людей подключаются к серверу через HTTP, и есть взаимно однозначное сопоставление между контекстами запросов и обратными вызовами. Таким образом, мы можем уйти с IntentService для обработки фоновых запросов и передать в ResultReceiver, чтобы заставить службу перезвонить в поток пользовательского интерфейса, когда запрос завершен / не выполнен:

http://developer.android.com/reference/android/os/ResultReceiver.html

Такая же общая техника должна применяться для длительных соединений сокетов, хотя вам, вероятно, придется выбирать другую форму обслуживания, чтобы вы могли самостоятельно управлять жизненным циклом. Но если вы это сделаете, вы сможете принять участие в ResultReceiver как часть запроса, поставить его в очередь для обработки и затем отправить () в ResultReceiver, чтобы получить обратный вызов в пользовательский интерфейс.