android 在不同的设备中通信两个应用程序
android communicating two apps in separate devices
这里的所有问题都指向 类 同一应用程序或不同进程中的不同应用程序,但在同一设备中。我想在两个单独的设备中向两个单独的应用程序发送数据或从两个单独的应用程序发送数据。我尝试使用 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);
还有其他方法可以实现吗?我的意思是向安装在另一台设备上的另一个应用程序发送数据或从另一个应用程序发送数据?
通过接受传入套接字连接的网络进行连接
在 Android 设备之间(或任何对等设备之间)执行此操作的常用方法是使用套接字。
您将一个或两个设备设置为 'listen' 用于套接字上的连接,然后在它们想要通信时接受来自另一个设备的连接(或者您可以有一个专用的客户端和服务器并且客户端始终启动连接)。
建立连接后,您可以来回发送消息。
有很多 Android 客户端服务器套接字应用程序的示例,但我发现有用的一个是:
- Android Server/Client example - client side using Socket(及其配套的服务器端博客文章 - link 包含在客户端博客中)
请注意,您可能需要在此之上添加自己的 'protocol' - 例如,如果您要发送长度未知且没有任何特殊 'end' 字符的文件,您可能需要添加一个字节(或几个字节来表示一个 int,long 等)在开始时指示传输的长度,以便接收方知道它何时收到了所有内容(或者在出现错误时它没有收到所有内容)。
通过不允许传入连接的网络进行连接(例如大多数 3G/4G)
在这些情况下,虽然理论上没有什么可以阻止套接字工作,但实际上许多移动运营商将不允许传入套接字连接。此外,您还需要找到移动设备的 public IP 地址,这是可能的,但非常复杂。如果您的解决方案只会 运行 在单个运营商网络上,您可以尝试看看它是否有效,但如果不是,您可能会发现使用 'middle':[=11 中的服务器更好更容易=]
- 设备A连接到服务器
- 设备 B 连接到服务器
- 设备 A 向服务器请求连接设备的地址,'discovers' 设备 B
- 设备A为设备B发送消息。它实际上将消息发送到服务器,并指示要发送到设备B
- 服务器通知设备 B 有一条消息可供它使用(例如使用某种消息通知,例如 Google 云消息,或者只是通过设备定期轮询以查看它们是否有任何消息) .
- 设备 B 从服务器检索消息
以上几乎适用于任何允许连接到 Internet 的网络。它确实有需要服务器的缺点,但它可能是大多数移动网络的必要方法。
如果您希望位于世界不同地区的两个不同设备上的 Android 应用程序的两个实例在没有服务器的情况下直接相互通信,那么最好的方法是使用 Tor 隐藏服务。 Tor 隐藏服务允许应用程序绕过防火墙或 NAT(当然,如果 Tor 未被阻止),并且设备可以轻松地相互通信而无需中央服务器。在这里,我将尝试给出一些您可以尝试的代码示例。最适合这个东西的库是 this.
步骤 1:将依赖项添加到 gradle.build 中的 app 模块:
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 步:向清单文件添加权限(Internet 权限或其他)。
第 3 步 (i):现在我们将只在 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();
}
}
完成了。 运行 您的应用程序并进行测试。如果您遇到困难,请尝试咨询 here.
所以,现在您的应用程序可以在没有任何中央服务器的情况下进行通信。 Tor 隐藏服务在这些用例中非常棒。
您也可以使用 IP6,然后您可以从一个 phone 到另一个进行直接套接字连接。我在不同的 4G 运营商(虽然在同一个国家/地区)上的两个 phone 之间的延迟低至 60 毫秒。请注意,您必须发送一些数据以避免切换到较低速度以获得如此低的延迟。 10 个并发 ping 对我来说足够了。
监听端根本不需要任何改变,客户端只需要使用IP6地址:
s = new Socket("2a10:811:21c:22a1:7683:ae1:18c7:9827", 9343);
IP6好像很多运营商都支持。如果不是,Tor 可以是一个很好的后备,如果延迟不是问题。
这里的所有问题都指向 类 同一应用程序或不同进程中的不同应用程序,但在同一设备中。我想在两个单独的设备中向两个单独的应用程序发送数据或从两个单独的应用程序发送数据。我尝试使用 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);
还有其他方法可以实现吗?我的意思是向安装在另一台设备上的另一个应用程序发送数据或从另一个应用程序发送数据?
通过接受传入套接字连接的网络进行连接
在 Android 设备之间(或任何对等设备之间)执行此操作的常用方法是使用套接字。
您将一个或两个设备设置为 'listen' 用于套接字上的连接,然后在它们想要通信时接受来自另一个设备的连接(或者您可以有一个专用的客户端和服务器并且客户端始终启动连接)。
建立连接后,您可以来回发送消息。
有很多 Android 客户端服务器套接字应用程序的示例,但我发现有用的一个是:
- Android Server/Client example - client side using Socket(及其配套的服务器端博客文章 - link 包含在客户端博客中)
请注意,您可能需要在此之上添加自己的 'protocol' - 例如,如果您要发送长度未知且没有任何特殊 'end' 字符的文件,您可能需要添加一个字节(或几个字节来表示一个 int,long 等)在开始时指示传输的长度,以便接收方知道它何时收到了所有内容(或者在出现错误时它没有收到所有内容)。
通过不允许传入连接的网络进行连接(例如大多数 3G/4G)
在这些情况下,虽然理论上没有什么可以阻止套接字工作,但实际上许多移动运营商将不允许传入套接字连接。此外,您还需要找到移动设备的 public IP 地址,这是可能的,但非常复杂。如果您的解决方案只会 运行 在单个运营商网络上,您可以尝试看看它是否有效,但如果不是,您可能会发现使用 'middle':[=11 中的服务器更好更容易=]
- 设备A连接到服务器
- 设备 B 连接到服务器
- 设备 A 向服务器请求连接设备的地址,'discovers' 设备 B
- 设备A为设备B发送消息。它实际上将消息发送到服务器,并指示要发送到设备B
- 服务器通知设备 B 有一条消息可供它使用(例如使用某种消息通知,例如 Google 云消息,或者只是通过设备定期轮询以查看它们是否有任何消息) .
- 设备 B 从服务器检索消息
以上几乎适用于任何允许连接到 Internet 的网络。它确实有需要服务器的缺点,但它可能是大多数移动网络的必要方法。
如果您希望位于世界不同地区的两个不同设备上的 Android 应用程序的两个实例在没有服务器的情况下直接相互通信,那么最好的方法是使用 Tor 隐藏服务。 Tor 隐藏服务允许应用程序绕过防火墙或 NAT(当然,如果 Tor 未被阻止),并且设备可以轻松地相互通信而无需中央服务器。在这里,我将尝试给出一些您可以尝试的代码示例。最适合这个东西的库是 this.
步骤 1:将依赖项添加到 gradle.build 中的 app 模块:
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 步:向清单文件添加权限(Internet 权限或其他)。
第 3 步 (i):现在我们将只在 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();
}
}
完成了。 运行 您的应用程序并进行测试。如果您遇到困难,请尝试咨询 here.
所以,现在您的应用程序可以在没有任何中央服务器的情况下进行通信。 Tor 隐藏服务在这些用例中非常棒。
您也可以使用 IP6,然后您可以从一个 phone 到另一个进行直接套接字连接。我在不同的 4G 运营商(虽然在同一个国家/地区)上的两个 phone 之间的延迟低至 60 毫秒。请注意,您必须发送一些数据以避免切换到较低速度以获得如此低的延迟。 10 个并发 ping 对我来说足够了。
监听端根本不需要任何改变,客户端只需要使用IP6地址: s = new Socket("2a10:811:21c:22a1:7683:ae1:18c7:9827", 9343);
IP6好像很多运营商都支持。如果不是,Tor 可以是一个很好的后备,如果延迟不是问题。