андроид, сообщающий два приложения на разных устройствах

Все вопросы здесь указывают на классы одного и того же приложения или разных приложений в отдельных процессах, но на одном устройстве. Я хотел бы отправить данные из двух отдельных приложений в два разных устройства. Я пробовал использовать 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 Скрытые службы настолько велики в этих случаях использования.