android communicating two apps in separate devices - android

All the questions here point to classes of the same app or different apps in separate processes yet in the same device. I would like to send data to and from two separate apps in two separate devices. I tried using broadcastreceiver but it didn't work. Here is my snippet to send the data.
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();
}
but when I receive the data in my other app using the following code snippet, It fails. When I debug the app I get null exception.
Intent intent = getIntent();
String action = intent.getAction();
String data = intent.getStringExtra(Intent.EXTRA_INTENT);
String type = intent.getType();
useraddress.setText(data);
startActivity(intent);
Is there another way to achieve this? I mean to send data to and from another app which is installed in another device?

Connecting over networks that accept incoming socket connections
The usual way to do this between Android devices (or between any peer devices) is to use sockets.
You set up one or both devices to 'listen' for connections on a socket and then accept a connection from the other when they want to communicate (or you can have a dedicated client and server and the client always initiates the connections).
Once the connection is established you can send messages back and forth.
There are many examples of Android client server socket applications, but one I found useful was:
Android Server/Client example - client side using Socket (and its companion server side blog article - link included in the client blog)
Note that you may have to add your own 'protocol' on top of this - for example if you are sending a file of unknown length without any special 'end' character, you may want to add a byte (or several byte to represent an int, long etc) at the start to indicate the length of the transmission so the receiving side knows when it has received everything (or that it has not received everything in case of an error).
Connecting over networks which do not allow incoming connections (e.g. most 3G/4G)
In these scenarios, while there is nothing theoretically stopping sockets working, in practice many mobile operators will not allow incoming socket connections. In addition you would need to find the public IP address of the Mobile, which is possible but is extra complexity. If your solution will only ever run on a single operators network you can experiment and see if it works, but if not you may find it better and easier to use a server in the 'middle':
Device A connectes to server
Device B connectes to server
Device A asks server for addresses of connected devices and 'discovers' device B
Device A send a message for device B. It actually sends the messages to the server with an indication that it is to be sent to device B
The server notifies device B that a message is available for it (using some sort of message notification like Google Cloud Messaging for example, or simply by the devices polling regularly to see if they have any messages).
Device B retrieves the messages from the server
The above will work on pretty much any network that allows connectivity to the internet. It does have the disadvantage of requiring a server but it is likely a necessary approach over most mobile networks.

If you want the two instances of your Android app on two different devices located on the different parts of the world to communicate with each other directly without the server, then the best way to do it is to use Tor Hidden Services. Tor Hidden Services allow the apps to bypass the firewall or NAT (if Tor is not blocked, of course), and the devices can easily communicate with each other without the need for a central server. Here, I will try to give some code examples that you can try. The best library suitable to this stuff is this.
Step 1: Add dependencies to your 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'
}
Step 2: Add permissions (Internet permissions or whatever) to your manifest file.
Step 3(i): Now we will just write the classic Client-Server programs in Java but with added Android and Tor flavor. To test this properly, try creating two different apps. One app will be the server and the other app will be a client. Preferably, you can even install the two apps on different phones.
In this example, we will try to send "Hello from Tor client" string from client app to server app.
For the server side: You can try this function inside any Activity and 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();
}
}
Step 3(ii): For the client side try this function
//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();
}
}
It's done. Run your apps and test it. If you get stuck, try consulting here.
So, now your apps can communicate without any central server. Tor Hidden Services are so awesome in these use cases.

You can also use IP6, then you can do a direct socket connection from one phone to the another. I got latency as low as 60ms between two phones on different 4G operators (in the same country though). Note that you have to send some data to avoid getting down switch to lower speed to get such low latency. 10 concurrent ping was enough for me.
The listen side doesn't need any change at all, the client side just has to use an IP6-address:
s = new Socket("2a10:811:21c:22a1:7683:ae1:18c7:9827", 9343);
IP6 seems to be supported by many operators. If not, tor can be a good fallback, if latency isn't a problem.

Related

How to receive files programmatically using bluetooth

I am trying to receive data (strings) from a Bluetooth enabled device whose MAC_ID is known.
I have searched many examples ,but each article is pointing to Bluetooth Chat example, I think in Bluetooth Chat example, application need to be installed on both the devices for them to be connected and exchange strings.Correct me if I am wrong.
But I need to install application only on Receiver device.I have tried installing the application only on one device and tried connecting to the sender device, without success.
Bluetooth is a peer to peer protocol where you need to have application running on both sides. Hence if you want to exchange data very good example would be Bluetooth chat. If you want to download or transfer a file you should either implement obex or FTP profile based applications.
Yes you need to deploy an application on both sides. If you are really restricted in a way that you only can deploy on one side, you have to figure out which standard protocols/bluetooth profiles the other side is capable of. You can figure that out by doing a SDP lookup. For a device, you will then get a list of UUIDs identifying these services. See the bluetooth spec for well known UUIDs. As #7383 pointed out, your are most probably looking for OBEX or FTP.
If you can deploy on both sides, you can write your own app using Blaubot (disclaimer: I wrote it). A simple Blaubot program would do this:
UUID MY_UUID = UUID.fromString("33bb1246-1472-11e5-b60b-1697f925ec7b");
// onCreate() or in a service, we create a blaubot instance
// using Bluetooth to form a network and Bluetooth + NFC to find devices
IBlaubotDevice ownDevice = new BlaubotDevice();
BlaubotUUIDSet uuidSet = new BlaubotUUIDSet(MY_UUID);
BlaubotBluetoothAdapter bluetoothAdapter = new BlaubotBluetoothAdapter(uuidSet, ownDevice);
BlaubotNFCBeacon nfcBeacon = new BlaubotNFCBeacon();
BlaubotBluetoothBeacon bluetoothBeacon = new BlaubotBluetoothBeacon();
this.mBlaubot = BlaubotAndroidFactory.createBlaubot(MY_UUID, ownDevice, adapter, nfcBeacon, bluetoothBeacon);
// start and wait until connected
this.mBlaubot.startBlaubot();
// create a channel and send your file
IBlaubotChannel fileChannel = this.mBlaubot.createChannel(1);
// convert your file to its bytes
File yourFile = // ... however you get it
byte[] fileBytes = ...// ... see http://stackoverflow.com/questions/858980/file-to-byte-in-java
// send it to all connected devices
fileChannel.publish(fileBytes, true);
// to receive it on the other device, do this:
// subscribe to the channel
fileChannel.subscribe(new IBlaubotMessageListener() {
#Override
public void onMessage(BlaubotMessage message) {
// extract your bytes from the message
byte[] fileBytes = message.getPayload();
// .. do something useful or write it to a file again
// to write it to a file
File file = new File(yourFilePath);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(fileBytes);
bos.flush();
bos.close();
}
});
This should be all you need. To allow the devices to connect, you have to pair them before or use NFC (just hold them together, when Blaubot is started). If you go with Blaubot let me know if you have problems that can't be solved with the documentation or the android quickstart guide.
I can only guess what your actual scenario looks like. If you have two android phones, this should work. If that is not the case, you should add more informations about the involved devices. Are we really talking about (classic) Bluetooth connections or are you trying to get data from a Bluetooth Low Energy device?
In this case the famous chat example will not help you either.

Android webpage interactivity

Lets say there are two android devices and a webpage.
On each of those devices there is a button being clicked and the webpage shows the accumulated clicks.
What makes this possible?
Are the android devices sending that data to a sql database and that counter is reading what currently is in that database?
Or can the device really send the information into the page?
The device can communicate data to the server or to the client side code. You can then have to decide what to do with the data. If you send it to the client side code then it would only update on one device, whereas sending it to the server would allow one click counter across every device.
Changing the page on the server side would add caching problems. So you probably want a data file instead, just a json or something that the server overwrites every time it receives another click.
This isn't very fast though and causes synchronisation issues between the users. For starters for a standard html page the client code is in charge of the calls to the server, so we would have to check the server periodically to see if the value has changed (say every 5 seconds).
A faster alternative would be to use a web socket. The client would keep a connection open to the server and listen for updates from the server, removing the need for our periodic check. Additionally the socket can be used to send clicks to the server and the server can keep the value in its memory removing the need for file writes.
Node.js can be downloaded from http://nodejs.org and this is the plug in I use for web sockets https://github.com/Worlize/WebSocket-Node.
So here is some server side code for a simple web socket server that parrots messages from 1 user to all users, including the user who sent it.
var connections = [];
var WebSocketServer = require('websocket').server;
var http = require('http');
var server = http.createServer(function(request, response) {
// process HTTP request. Since we're writing just WebSockets server
// we don't have to implement anything.
});
server.listen(1337, function() { });
// create the server
wsServer = new WebSocketServer({
httpServer: server
});
// WebSocket server
wsServer.on('request', function(request) {
//got a new user requesting a connection, so lets accept and store them
var connection = request.accept(null, request.origin);
connections.push(connection);
connection.on('message', function(message) { //inbound message
if (message.type === 'utf8') {
// process WebSocket message
send(message.utf8Data); //bounce to everyone else
console.log(message);
}
});
});
setInterval(function(){console.log(connections.length +" :users");},5000);
//every 5 seconds, tell us how many users we have
function send(message){
var i = connections.length;
while(i--)
connections[i].send(message);
//send the message to all users
}
Example client side
<html><head><script>
var connection, connIsActive = false;
// if user is running mozilla then use it's built-in WebSocket
window.WebSocket = window.WebSocket || window.MozWebSocket;
connection = new WebSocket('ws://127.0.0.1:1337');
connection.onopen = function () {
// connection is opened and ready to use
connIsActive = true;
console.log('Connection loaded');
};
connection.onerror = function (error) {
// an error occurred when sending/receiving data
connIsActive = false
console.log('error');
};
connection.onmessage = function (message) {
// handle incoming message
console.log(message.data);
};
function send(message){
if(connIsActive)connection.send(message);
}
</script></head></html>
Save the first snippet as "myserver.js" (or similar) and start it up in node via command line. Save the second snippet as a "client.html" and open it on 2 devices, or just 2 browser instances. Theres no interface on the client but you can send and receive messages from the debug console using send("message string")
Provided you can wrap your head around my snippets, modifying it to work like your example should prove fairly easy!
To achieve what you are trying to do, you need to learn socket programming for android.
In order to use two device(clients) you also need to learn port forwarding for servers.
To begin try this tutorial.

What is the quickest way to detect if a service on a specific IP is available

My Android program has to scan 255 LAN addresses to find if an OData service (WCF Data Service) is available.
The service runs on 1 or 2 computers, there are about 20 devices on the LAN but when my code "scans" an IP address that is in use BUT not hosting the service it doesn't throw exception immediatley instead it waits for a long time so finding 2 addresses took 10 minutes.
Here is the code:
try
{
String url = String.format("http://%s/InformationService/InformationService.svc/", ip);
ODataConsumer consumer = ODataJerseyConsumer.create(url);
Enumerable<OObject> result= consumer.callFunction("CheckInformation")
.execute();
Log.i("DEBUG", "Service available: " + ip);
}
catch (Throwable e)
{
//e.printStackTrace();
Log.i("DEBUG", "No service: " + ip);
}
Why does it wait at the reserved IPs if the service is not hosted there?
How can I detect immediately if there is no service there?
First thing i would say is that just to check url's availability, you need not make a call to service method.
And then from your post it's not clear that,
whether you ONLY want to check if svc(wcf) exists on the given url(on specific IP)
OR
you also want to check that if wcf exits there, is it available to take calls?
In any case, if you refer these 2 links on SO itself, i feel you would certainly get what you are looking for.
Test availablity of WCF URL
C# How can I check if a URL exists/is valid?
Note: I have not done this kind of checks on android anytime, but in general when you want to check if a wcf (or any web url is valid one like check if svc exits there on a url), then you can simply make a web get request for the web url(not just wcf svc ones) and if you get response with valid http status, then it's valid url.

Android TCP/IP Socket Communication Fails To Return Data

I am currently working on an Android app to be linked into an existing product for my employer. The system is a device running firmware that is controllable via serial, ethernet, or wi-fi using a .NET Windows program, direct serial communication, or a control webpage. The Android app is meant to auto-connect control webpage so that the device is controllable from a phone without anyone having to manually find IP addresses. In order to do that, I need to be able to find IP addresses and determine whether or not the address corresponds to one of these firmware devices.
Essentially what I want to do is run through all IP addresses that the Android sees and send each one to the method above. This thing should ping the address with a firmware command and see what is sent back to determine whether the address corresponds to a firmware device. I’ve been doing that at the moment by sending a command like "HOME" or "GETINFO" (correctly formatted for the firmware, of course) and comparing what, if anything is sent back with the expected response. Commands like home also have the benefit of causing a physical response, so we know without a microchip debugger if the command has at least been received.
As it stands I have the correct address hardcoded and sent in to this method. I know that the app can load the webpage controls successfully using the same address as a URL, so it must be correct and the connection must be good, but direct communication to the device is not working. No physical response is observed and no information is sent back—the Input stream just times out and returns -1. What’s stumping me so badly about this is that as far as I can tell, I’m sending information exactly the same way as the .NET Windows controls, and yet it isn’t working.
One further note: I’m aware that sending the IP Address string to the socket constructor as a hostname probably should not work, but since no UnknownHostException is thrown, I know that the socket can resolve it to an IP Address. Correct?
My code is as follows:
private class NetworkTask extends AsyncTask<String, Boolean, Boolean> {
protected Boolean doInBackground(String... addr){
try {
String message = "<FHGETHUBINFO>";
byte[] input = new byte[8];
//addr is an array of string parameters containing a single IP address string. E.g. addr[0]=”192.168.199.108”
Socket s = new Socket(addr[0],80);
//outgoing stream redirect to socket
OutputStream out = s.getOutputStream();
out.write(message.getBytes());
Log.v(TAG, "output sent. Waiting for input.");
InputStream in = s.getInputStream();
//Skip the exclamation mark and newline. Verified that nothing is received even without a skip.
in.skip(2);
int numBytes = in.read(input,0,8);
Log.v(TAG, "Input received: "+numBytes);
String st = input.toString();
//Close connection
s.close();
if(st != "HUB INFO"){
return true;
}
else{
return false;
}
}
catch (UnknownHostException e) {
Log.v(TAG,"UnknownHostException: "+e.getMessage());
e.printStackTrace();
}
catch (IOException e) {
Log.v(TAG,"IOException: "+e.getMessage());
e.printStackTrace();
}
return false;
Thanks for any help you can give, I really appreciate it!
Agreed that I should be calling isReachable on the socket just for verification purposes, so thanks for the tip! However, it turned out the problem was that the device is not communicating on port 80, so the fact that I have the wrong port is definitely the source of the problem. Thank you for the advice, regardless.

How to send and receive data in Android Programming using bluetooth without pairing?

I am new to Android programming, and have java concept, I want to know that how can I send and receive data using bluetooth without pairing or any password (Only if both device has my app installed),
any suggestion?
As far as I know it's impossible to send or receive data over RFCOMM sockets without pairing. I've tried this extensively with an application that I'm developing. My results are:
If the two devices are paired and discoverable, bi-directional communication is possible
If the two devices are paired, but the "server" device (the one the android device is trying to connect to) is set to be not discoverable, then bi-directional communication is still possible
If the two devices are not paired, but the "server" device is discoverable, then a pairing request is still required before bi-directional communication is possible. This means that RFCOMM client sockets (i.e., those from Android) require the devices to be paired. This was tested on a Samsung Captivate running Android 2.2. I find this very strange, as I can understand requiring pairing before allowing RFCOMM server sockets, but requiring pairing for client sockets is a bit stringent.
As #ethrbunny mentioned you can also just use WiFi, setup parallel server/client threads on each device, and send whatever you want. To discover services on a local network you can optionally use zeroconf.
I got the the following from this Google groups post by Kristopher Micinski.
Hope it helps.
I believe the key to getting this to work is in the mUuid list.
Take a close look at what this is doing:
for (int i = 0; i < Connection.MAX_SUPPORTED && myBSock == null; i++) {
for (int j = 0; j < 3 && myBSock == null; j++) {
myBSock = getConnectedSocket(myBtServer, mUuid.get(i));
if (myBSock == null) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Log.e(TAG, "InterruptedException in connect", e);
}
}
}
}
What this code does is looks to connect to the device, but how does it
do so? It tries the socket multiple times, using multiple UUIDs for
the session.
In essence it means that we can use UUID only once. So instead this
application implements using seven UUIDs, then the server listens and
accepts each UUID on the server side, this is what is done with the
following code:
for (int i = 0; i < Connection.MAX_SUPPORTED && maxConnections > 0; i++) {
BluetoothServerSocket myServerSocket = mBtAdapter.listenUsingRfcommWithServiceRecord(srcApp, mUuid.get(i));
BluetoothSocket myBSock = myServerSocket.accept();
myServerSocket.close(); // Close the socket now that the
// connection has been made.
String address = myBSock.getRemoteDevice().getAddress();
mBtSockets.put(address, myBSock);
mBtDeviceAddresses.add(address);
Thread mBtStreamWatcherThread = new Thread(new BtStreamWatcher(address));
mBtStreamWatcherThread.start();
mBtStreamWatcherThreads.put(address, mBtStreamWatcherThread);
maxConnections = maxConnections - 1;
if (mCallback != null) {
mCallback.incomingConnection(address);
}
}
Now, on the client side of things what is done? The client does not
know how many active connections the server currently has.
If we have some agreed upon order that the clients must use we can
simply use this, however, in our case, we simply just try each UUID
in sequence until we "find the right one."
Short version: -- Use multiple UUIDs, you can only use one at once. So define seven (max for piconet usage) and try each one until
you find the right one.

Categories

Resources