android связывает два приложения на разных устройствах
Все вопросы здесь указывают на классы одного и того же приложения или разных приложений в отдельных процессах, но в одном и том же устройстве. Я хотел бы отправлять данные в два отдельных приложения и с двух разных устройств. Я попробовал использовать broadcastreceiver, но это не сработало. Вот мой фрагмент для отправки данных.
addressstring = String.valueOf(acrilocation.getText());
if (addressstring != null && addressstring.length() > 0){
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Constants.LOCATION_DATA_EXTRA, addressstring);
intent.setType("text/plain");
sendBroadcast(intent);
} else{
Toast.makeText(getApplicationContext(), "Enter valid location address", Toast.LENGTH_SHORT).show();
}
Но когда я получаю данные в другом приложении, используя следующий фрагмент кода, это не удается. Когда я отлаживаю приложение, я получаю нулевое исключение.
Intent intent = getIntent();
String action = intent.getAction();
String data = intent.getStringExtra(Intent.EXTRA_INTENT);
String type = intent.getType();
useraddress.setText(data);
startActivity(intent);
Есть ли другой способ достичь вот это? Я имею в виду, чтобы отправлять данные и из другого приложения, которое установлено в другом устройстве?
2 ответа:
Подключение по сетям, принимающим входящие сокетные соединения
Обычный способ сделать это между устройствами Android (или между любыми одноранговыми устройствами) - использовать сокеты.
Вы настраиваете одно или оба устройства для "прослушивания" соединений на сокете, а затем принимаете соединение от другого, когда они хотят общаться (или у вас может быть выделенный клиент и сервер, и клиент всегда инициирует соединения).
Как только соединение установлено, вы можете отправляйте сообщения туда и обратно.
Есть много примеров приложений сокетов клиент-сервер Android, но один из них я нашел полезным:
- пример сервера/клиента Android-клиентская сторона, использующая сокет (и сопутствующая статья блога на стороне сервера-ссылка, включенная в блог клиента)
Обратите внимание, что вам, возможно, придется добавить свой собственный "протокол" поверх этого - например, если вы отправляете файл неизвестной длины без какого-либо специального символа "конец", вы можете захотеть чтобы добавить байт (или несколько байт для представления int, long и т. д.) В начале, чтобы указать длину передачи, чтобы принимающая сторона знала, когда она получила все (или что она не получила все в случае ошибки).
Подключение по сетям, которые не позволяют входящие соединения (например, большинство 3G/4G)
В этих сценариях, хотя теоретически ничто не останавливает работу сокетов, на практике многие мобильные операторы не разрешают входящий разъемные соединения. Кроме того, вам нужно будет найти публичный IP-адрес мобильного телефона, что возможно, но является дополнительной сложностью. Если ваше решение когда-либо будет работать только на одной сети операторов, вы можете поэкспериментировать и посмотреть, работает ли оно, но если нет, вы можете найти его лучше и проще использовать сервер в "середине":
- Устройство a подключается к серверу
- Устройство B подключается к серверу
- устройство а запрашивает у сервера адреса подключенных устройств и "обнаруживает" устройство B
- Устройство A отправляет сообщение для устройства B. оно фактически отправляет сообщения на сервер с указанием, что оно должно быть отправлено устройству B
- сервер уведомляет устройство B о том, что для него доступно сообщение (используя какое-либо уведомление о сообщении, например Google Cloud Messaging, или просто регулярно опрашивая устройства, чтобы узнать, есть ли у них какие-либо сообщения).
- Устройство B получает сообщения от сервера
Вышесказанное будет работать в значительной степени любая сеть, которая позволяет подключиться к интернету. У него есть недостаток, требующий сервера, но это, вероятно, необходимый подход в большинстве мобильных сетей.
Если вы хотите, чтобы два экземпляра вашего Android-приложения на двух разных устройствах, расположенных в разных частях мира, напрямую взаимодействовали друг с другом без сервера, то лучший способ сделать это-использовать скрытые сервисы Tor. Скрытые сервисы Tor позволяют приложениям обходить брандмауэр или NAT (если Tor не заблокирован, конечно), и устройства могут легко взаимодействовать друг с другом без необходимости центрального сервера. Здесь я постараюсь привести несколько примеров кода, которые вы можете пробовать. Лучшая библиотека, подходящая для этого материала, - этоthis .
Шаг 1 : добавьте зависимости в свой gradle.build in app module:
allprojects { repositories { maven { url 'https://jitpack.io' } } } dependencies { compile 'com.github.jehy:Tor-Onion-Proxy-Library:0.0.7' compile 'org.slf4j:slf4j-api:1.7.7' compile 'org.slf4j:slf4j-android:1.7.7' }
Шаг 2 : добавьте разрешения (разрешения интернета или что-то еще) в файл манифеста.
Шаг 3 (i): Теперь мы просто напишем классические клиент-серверные программы на Java, но с добавлением Android и Tor. Чтобы проверить это должным образом, попробуйте создать два разных приложения. Одним из приложений будет сервер и другое приложение будут клиентом. Предпочтительно, вы даже можете установить эти два приложения на разных телефонах. В этом примере мы попытаемся отправить строку "Hello from Tor client" из клиентского приложения в серверное приложение.
для серверной части: вы можете попробовать эту функцию внутри любого действия и AsyncTask.
void server(Context context){ //For comments and documentation, visit the original repo //https://github.com/thaliproject/Tor_Onion_Proxy_Library String fileStorageLocation = "hiddenservicemanager";; com.msopentech.thali.toronionproxy.OnionProxyManager onionProxyManager = new com.msopentech.thali.android.toronionproxy.AndroidOnionProxyManager(context, fileStorageLocation); int totalSecondsPerTorStartup = 4 * 60; int totalTriesPerTorStartup = 5; try { boolean ok = onionProxyManager.startWithRepeat(totalSecondsPerTorStartup, totalTriesPerTorStartup); if (!ok) System.out.println("Couldn't start tor"); while (!onionProxyManager.isRunning()) Thread.sleep(90); System.out.println("Tor initialized on port " + onionProxyManager.getIPv4LocalHostSocksPort()); int hiddenServicePort = 8080; int localPort = 9343; String onionAddress = onionProxyManager.publishHiddenService(hiddenServicePort, localPort); System.out.println("Tor onion address of the server is: "+onionAddress); ServerSocket serverSocket = new ServerSocket(localPort); while(true) { System.out.println("Waiting for client request"); Socket receivedSocket = serverSocket.accept(); ObjectInputStream ois = new ObjectInputStream(receivedSocket.getInputStream()); String message = (String) ois.readObject(); //Here we will print the message received from the client to the console. /*You may want to modify this function to display the received string in your View.*/ System.out.println("Message Received: " + message); } } catch (Exception e) { e.printStackTrace(); } }
Шаг 3 (ii): для клиентской стороны попробуйте эту функцию
//Inputs: //'String onionAddress' should be the one obtained in server() function. //It will be printed in the console and it will possibly remain the same //even if the app restarts, because all the data/cache will be stored locally. //Also, when you run the code for the first time, Tor will take about 1 or 2 mins //to bootstrap. In the subsequent runs, Tor will start relatively faster as the //data will be cached. 'int hiddenServicePort' is the port at which the hidden //service has started on the server. In our example code, it is 8080. So, pass that here void client(Context context, String onionAddress, int hiddenServicePort){ String fileStorageLocation = "clientmanager"; com.msopentech.thali.toronionproxy.OnionProxyManager onionProxyManager = new com.msopentech.thali.android.toronionproxy.AndroidOnionProxyManager(context, fileStorageLocation); int totalSecondsPerTorStartup = 4 * 60; int totalTriesPerTorStartup = 5; try { boolean ok = onionProxyManager.startWithRepeat(totalSecondsPerTorStartup, totalTriesPerTorStartup); int socksPort=onionProxyManager.getIPv4LocalHostSocksPort(); if (!ok) System.out.println("Couldn't start tor in client"); while (!onionProxyManager.isRunning()) Thread.sleep(90); System.out.println("Client Tor initialized on port " + socksPort); System.out.println("Client is waiting for the server to get ready"); Thread.sleep(2000); Socket clientSocket = Utilities.socks4aSocketConnection(onionAddress, hiddenServicePort, "127.0.0.1", socksPort); ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream()); oos.writeObject("Hello from Tor client\n"); System.out.println("Client has sent the message"); oos.close(); } catch (Exception e) { e.printStackTrace(); } }
Дело сделано. Запускайте свои приложения и тестируйте их. Если вы застряли, попробуйте проконсультироваться здесь .
Итак, теперь ваши приложения могут взаимодействовать без центрального сервера. Скрытые сервисы Tor настолько удивительны в этих случаях использования.