андроид, сообщающий два приложения на разных устройствах
Все вопросы здесь указывают на классы одного и того же приложения или разных приложений в отдельных процессах, но на одном устройстве. Я хотел бы отправить данные из двух отдельных приложений в два разных устройства. Я пробовал использовать 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();
}
но когда я получаю данные в другом приложении, используя следующий фрагмент кода, он терпит неудачу. Когда я отлаживаю приложение, я получаю null-исключение.
Intent intent = getIntent();
String action = intent.getAction();
String data = intent.getStringExtra(Intent.EXTRA_INTENT);
String type = intent.getType();
useraddress.setText(data);
startActivity(intent);
Есть ли другой способ достичь этого? Я хочу отправить данные в другое приложение, которое установлено на другом устройстве, и обратно?
Ответы
Ответ 1
Подключение по сетям, которые принимают входящие соединения сокетов
Обычный способ сделать это между устройствами Android (или между любыми одноранговыми устройствами) - использовать сокеты.
Вы настроили одно или оба устройства на "прослушивание" соединений в сокете, а затем принимаете соединение друг с другом, когда они хотят общаться (или вы можете иметь выделенный клиент и сервер, а клиент всегда инициирует подключения).
После установления соединения вы можете отправлять сообщения взад и вперед.
Существует множество примеров приложений сокетов для клиентских серверов Android, но я нашел полезным:
Обратите внимание, что вам может потребоваться добавить свой собственный "протокол" поверх этого - например, если вы отправляете файл с неизвестной длиной без специального символа "конец", вы можете захотеть добавить байт (или несколько байт для представления int, long и т.д.) в начале указать длину передачи, чтобы получающая сторона узнала, когда она получила все (или что она не получила все в случае ошибки).
Подключение по сетям, которые не позволяют входящие соединения (например, большинство 3G/4G)
В этих сценариях, пока теоретически не прекращаются работы сокетов, на практике многие мобильные операторы не разрешают входящие соединения сокетов. Кроме того, вам нужно будет найти общедоступный IP-адрес Mobile, что возможно, но является дополнительной сложностью. Если ваше решение будет работать только в одной сети операторов, вы можете поэкспериментировать и посмотреть, работает ли оно, но если нет, вам может быть проще и проще использовать сервер в "середине":
- Устройство A подключается к серверу
- Устройство B подключается к серверу
- Устройство A запрашивает сервер для адресов подключенных устройств и "обнаруживает" устройство B
- Устройство A отправляет сообщение для устройства B. Фактически он отправляет сообщения на сервер с указанием, что он должен быть отправлен на устройство B
- Сервер уведомляет устройство B о том, что сообщение доступно для него (например, с помощью какого-либо уведомления о сообщениях, например Google Cloud Messaging, или просто обычным опросом устройств, чтобы узнать, есть ли у них какие-либо сообщения).
- Устройство B получает сообщения с сервера
Вышеупомянутая работа будет работать практически в любой сети, которая позволяет подключаться к Интернету. У него есть недостаток в требовании сервера, но он, вероятно, необходим для большинства мобильных сетей.
Ответ 2
Если вы хотите, чтобы два экземпляра вашего Android-приложения на двух разных устройствах, расположенных в разных частях мира, связывались друг с другом напрямую без сервера, лучший способ сделать это - использовать Tor Hidden Services. Tor Hidden Services позволяет приложениям обойти брандмауэр или NAT (если, конечно, Tor не заблокирован), и устройства могут легко обмениваться данными друг с другом без необходимости центрального сервера. Здесь я попытаюсь привести примеры кода, которые вы можете попробовать. Это лучшая библиотека, подходящая для этого.
Шаг 1: добавьте зависимости к вашему gradle.build в модуле приложения:
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): Теперь мы просто напишем классические программы Client-Server на Java, но с добавлением Android и Tor. Чтобы проверить это правильно, попробуйте создать два разных приложения. Одно приложение будет сервером, а другое приложение будет клиентом. Вы даже можете установить два приложения на разных телефонах. В этом примере мы попытаемся отправить строку "Hello from Tor client" из клиентского приложения на серверное приложение.
Для серверной части: вы можете попробовать эту функцию внутри любой Activity и 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 Скрытые службы настолько велики в этих случаях использования.