How to transfer "data" between two device (android,iphone)? - android

How can i transfer data between two device? I would like to transfer data (mostly image file) between different platforms (android,iphone). Is it possible to use p2p or should i use client-server?
Any help will be appreciated.

Have you looked at Qualcomm's AllJoyn library? It works over Bluetooth or wifi only.
The below code is copied from this Incorporating Socket Programming into your Applications
public class ServerActivity extends Activity {
private TextView serverStatus;
// default ip
public static String SERVERIP = "10.0.2.15";
// designate a port
public static final int SERVERPORT = 8080;
private Handler handler = new Handler();
private ServerSocket serverSocket;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.server);
serverStatus = (TextView) findViewById(R.id.server_status);
SERVERIP = getLocalIpAddress();
Thread fst = new Thread(new ServerThread());
fst.start();
}
public class ServerThread implements Runnable {
public void run() {
try {
if (SERVERIP != null) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Listening on IP: " + SERVERIP);
}
});
serverSocket = new ServerSocket(SERVERPORT);
while (true) {
// listen for incoming clients
Socket client = serverSocket.accept();
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Connected.");
}
});
try {
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
Log.d("ServerActivity", line);
handler.post(new Runnable() {
#Override
public void run() {
// do whatever you want to the front end
// this is where you can be creative
}
});
}
break;
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Oops. Connection interrupted. Please reconnect your phones.");
}
});
e.printStackTrace();
}
}
} else {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Couldn't detect internet connection.");
}
});
}
} catch (Exception e) {
handler.post(new Runnable() {
#Override
public void run() {
serverStatus.setText("Error");
}
});
e.printStackTrace();
}
}
}
// gets the ip address of your phone's network
private String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
InetAddress inetAddress = enumIpAddr.nextElement();
if (!inetAddress.isLoopbackAddress()) { return inetAddress.getHostAddress().toString(); }
}
}
} catch (SocketException ex) {
Log.e("ServerActivity", ex.toString());
}
return null;
}
#Override
protected void onStop() {
super.onStop();
try {
// make sure you close the socket upon exiting
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

If you are OK with Bump, Then they provide an API for the developers to use and its pretty simple to use. Check this out.
To see a live demo of transferring between iOS and Android # youtube.
Detailed code snippet and example in Github.
PS: i don't belong to bu.mp :).

While p2p is possible in some cases, you will achieve the most widespread compatibility with a client-server architecture, at the cost of having to deploy, power, connect, and maintain servers.
You will be able to use both wifi access points and mobile (3g, etc) networks
You have a ready place in the system to measure (or restrict) usage and/or insert ads
You don't have to worry about firewalls blocking inbound connections to the devices (common on wifi, almost always the case on mobile)
Relative locations of the devices are irrelevant
You can interoperate not only with smartphones and tablets, but with traditional PCs and laptops

I would use a WebService. That makes it easier to maintain your service, becuase the Service Implementation is independent of your app.
Pro Webservice:
Reachable under a pre configured DNS
Modifications on the Service do not affect the Application (No updates needed on possible bugfixes)
Contra Webservice:
All the traffic goes through your Server
Application relies on your Server
The you should ask yourself the question, how much data is transferred in your communication? Is there a real benefit of using direct connections?

You can use filehub to transfer files between IOS and android.
there is a new device called fielhub on the market can transfer photos/movies/music between iOS and Android Devices, or between mobile devices and SD Card/USB HDD.. I think it is called ravpower filehub.

Related

MulticastSocket on port 80

I would like to create a network application where some devices have to send a packet to the same another device. This device is an Android one. My idea is to broadcast the message to the network so that the device will get it. I have checked on the Internet and I have found that one solution might be the MulticastSocket. I've followed the tutorial from the javadoc and this is quite easy. I did it on my Android phone and on one computer. The problem I have now is the fact that I want this socket to be bound on port 80. Effectively, I get an error, more precisely an EACCES when I try to create the socket. Here is the code of my server :
public class MyServer extends Thread {
private int port;
private boolean isRunning = true;
private MulticastSocket socket;
private InetAddress group;
public MyServer(int port) {
this.port = port;
isRunning = true;
}
public void run() {
socket = null;
try {
socket = new MulticastSocket(80);
group = InetAddress.getByName("coucou");
socket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
return;
}
while (isRunning) {
DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);
try {
socket.receive(packet);
Log.i("Server", "Packet received");
MyCipher rec = new MyCipher(Arrays.copyOfRange(packet.getData(), 0, packet.getLength()));
Receiver.getInstance().put(rec);
} catch (IOException e) {
e.printStackTrace();
}
}
socket.close();
}
public void mustStop() {
this.notify();
isRunning = false;
}
}
Does someone have an idea how to fix it ? Furthermore, does someone know if the name of the group must be the ip of the server or might it be a "random" string ?
Thank you !

How can I connect two Android device by socket without server

I am trying to develop an android application that can exchange data on peer to peer connection with other devices without server. So please suggest how can I do this. Thank you in advance.
This is a complete code for chat by SocketProgramming without server.
In my Application, first you are a client and you search for a server. When you do not find any server, you become a server and wait for a client.
public class MainActivity extends ActionBarActivity {
private Handler handler = new Handler();
private TextView text;
private EditText input;
private Button send;
private Socket socket;
private DataOutputStream outputStream;
private BufferedReader inputStream;
private String DeviceName = "Device";
private boolean searchNetwork() {
log("Connecting");
String range = "192.168.56.";
for (int i = 1; i <= 255; i++) {
String ip = range + i;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ip, 9000), 50);
outputStream = new DataOutputStream(socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
DeviceName += "1";
Log.i("Server", DeviceName);
log("Connected");
return true;
} catch (Exception e) {
}
}
return false;
}
private void runNewChatServer() {
ServerSocket serverSocket;
try {
serverSocket = new ServerSocket(9000);
log("Waiting for client...");
socket = serverSocket.accept();
DeviceName += "2";
log("a new client Connected");
} catch (IOException e) {
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
input = (EditText) findViewById(R.id.input);
send = (Button) findViewById(R.id.send);
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
if (!searchNetwork()) {
runNewChatServer();
}
outputStream = new DataOutputStream(
socket.getOutputStream());
inputStream = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
while (true) {
String Message = inputStream.readLine();
if (Message != null) {
log(Message);
}
}
} catch (IOException e) {
log("Error: IO Exception");
e.printStackTrace();
}
}
});
send.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
if (outputStream == null) {
return;
}
try {
String Message = input.getText().toString() + "\n";
outputStream.write(Message.getBytes());
log2(input.getText().toString());
} catch (IOException e) {
e.printStackTrace();
}
input.setText("");
}
});
thread.start();
}
private void log(final String message) {
handler.post(new Runnable() {
String DeviceName2="";
#Override
public void run() {
if (DeviceName.equals("Device1")) {
DeviceName2 = "Device2";
}else if(DeviceName.equals("Device2")) {
DeviceName2 = "Device1";
}else{
DeviceName2 = "UnknowDevice";
}
text.setText(text.getText() + "\n" + DeviceName2 + " :"
+ message);
}
});
}
private void log2(final String message) {
handler.post(new Runnable() {
#Override
public void run() {
text.setText(text.getText() + "\n" + "you" + " :"
+ message);
}
});
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.exit(0);
return true;
}
return super.onKeyDown(keyCode, event);
}
}
Your design has a big problem : ...
If there is no central server some android devices should act as client and others as server but this will not work in some situations:
When the mobile telephony provider assigns private and non-public IP
When the device is connected to a Wi-Fi network but no NAT rule is defined on the router.
In both cases the problem is that the listening port of the device that must act as server is unreachable.
Java provides ServerSocket and Socket to communicate b/w devices. One of the device you can make as server and other device you can make as client and communicate b/w 'em without introducing server hosted on some machine.
The Other and better option is Using Wi-Fi Peer-to-Peer. WifiP2pManager help you to achieve your purpose.Here is an example.
If you're looking for such P2P over a local network, there are two parts to it:
Discovering peers
Communicating with peers
Among Android APIs, you can either use Network Service Discovery APIs for this or Wifi P2P Service Discovery APIs.
There's a wrapper library which which uses these internally and has comparatively better documentation - Salut, which can also be used.
I also created a library for P2P - Near, which uses sockets directly. The problem I was facing with Android APIs was that discovery wasn't happening with certainty every time and the underlying issue was unknown.
If you're looking for P2P across the internet, socket IO is a prevalent solution. Even Near should be able to facilitate the transfers if you provide the IP addresses and they're not behind NAT firewalls.

Android can not receive multicast packet

I'm playing a little bit with multicast sockets. I write a server which sends a message to a android client. Until yet the client should only log the received message.
I noticed that no multicast packet are received on my device.
Here is the code for the server (runs on the pc):
public class MulticastServer{
private int port;
private boolean running = false;
private MulticastSocket serverSocket;
private InetAddress group;
private String multicastAddress = "230.192.0.11";
public MulticastServer(int port) {
super();
this.port = port;
init();
}
public MusicStreamerServer() {
this(5500);
}
private void init() {
try {
group = InetAddress.getByName(multicastAddress);
serverSocket = new MulticastSocket(port);
serverSocket.joinGroup(group);
} catch (IOException e) {
e.printStackTrace();
}
}
public void start() throws IOException {
System.out.println("server started");
if (running)
return;
running = true;
new Thread(new Runnable() {
#Override
public void run() {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length,
group, port);
String msg = "msg";
while (running) {
packet.setData(msg.getBytes(), 0, msg.length());
try {
serverSocket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void stop() throws IOException {
running = false;
} }
Here is the code for the android client:
public class MainActivity extends Activity {
private MulticastSocket socket;
private InetAddress group;
private String multicastAddress = "230.192.0.11";
private int port = 5500;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
group = InetAddress.getByName(multicastAddress);
socket = new MulticastSocket(port);
socket.joinGroup(group);
socket.setBroadcast(true);
} catch (IOException e) {
e.printStackTrace();
Log.wtf("init", e.getMessage());
}
new Thread(new Runnable() {
#Override
public void run() {
WifiManager wm = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiManager.MulticastLock multicastLock = wm
.createMulticastLock("mylock");
multicastLock.acquire();
byte[] buf = new byte[1024];
while (true) {
try {
socket.receive(packet);
Log.d("receiver","received = " + (new String(packet.getData())));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}}
I've tested the code with 2 different devices. The Nexus4 and the Nexus7 (2013) both running the latest Android.
Could anybody help me?
Thanks
I've seen that the issue is really inconsistent.
Android version: 4.2.x
On Samsung S4 active:
Multicast is working as expected.
On Samsung Note 10.1 and Nexus 4.2.3
Multicast is not working as expected.
239.x.x.x is not supported (and sadly it's the one used to multicast television...)
224.0.0.251 is working as expected.
I think they have a bug with the mask.
A multicast address is normally
|1 1 1 0| MULTICAST Address | 224.0.0.0 - 239.255.255.255
11100000.00000000.00000000.00000001 = 224.0.0.1
11101111.00000000.00000000.00000001 = 239.0.0.1
So the mask should be 224.0.0.0/4 and not 224.0.0.0/8
Does your manifest request the proper permissions?
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
Also, you may want to play with the Advanced settings in the WiFi menu on your phone, both Wi-Fi optimizations and Keep Wi-Fi on during sleep may impact your ability to do multicasts.

Android socket still can write without exception when wifi has been disconnected

I write an Android socket demo which just post user's input to server.
I establish a socket from android client through wifi connection, and everything goes well, the server can receive the message send from android client. The problem is, then I close WIFI of phone, but the socket can write without exception.
The code of Android client:
public class MyActivity extends Activity {
private SocketHandlerThread thread;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
thread = new SocketHandlerThread("ScoketTest");
thread.start();
}
class SocketHandlerThread extends HandlerThread {
private Socket socket;
private Handler handler;
public SocketHandlerThread(String name) {
super(name);
}
public SocketHandlerThread(String name, int priority) {
super(name, priority);
}
#Override
public void run() {
try {
socket = new Socket("192.168.60.184", 1990);
} catch (IOException e) {
Log.e("SocketTest", e.getLocalizedMessage(), e);
}
super.run();
}
Handler getHandler() {
if (handler == null) {
handler = new Handler(getLooper());
}
return handler;
}
void send(final String text) {
Runnable runnable = new Runnable() {
public void run() {
Log.e("SocketTest", "Start send text: " + text);
try {
socket.getOutputStream().write((text + "\n").getBytes());
socket.getOutputStream().flush();
} catch (Exception e) {
Log.e("SocketTest", e.getLocalizedMessage(), e);
}
Log.e("SocketTest", "Text has been send:" + text);
}
};
getHandler().post(runnable);
}
#Override
protected void onLooperPrepared() {
runOnUiThread(new Runnable() {
#Override
public void run() {
findViewById(R.id.button).setEnabled(true);
}
});
}
}
public void send(View view) {
String text = ((EditText) findViewById(R.id.text)).getText().toString();
thread.send(text);
}
}
The code of Server:
public class SocketTestServer {
ServerSocket serverSocket;
SocketTestServer() throws IOException {
serverSocket = new ServerSocket(1990);
}
void start() throws IOException {
Socket clientSocket = serverSocket.accept();
clientSocket.getInputStream();
PrintWriter out = new PrintWriter(System.out, true);
BufferedReader in =
new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
out.println(inputLine);
}
}
public static void main(String[] args) throws IOException {
SocketTestServer server = new SocketTestServer();
server.start();
}
}
I try on several phones. On Galaxy Nexus(4.2.1) an exception was thrown as expected, but on some MOTO or HTC phones socket can still write without any exception, which means I may loss some messages that I thought has been received successfully.
How could I get known that the socket connection was broken on any type of phone?
Any suggestion will be appreciated.
p.s
I know the Connective Change Broadcast, but before receive the broadcast the client may have write some message through the broken socket.
Though adding receive check on application protocol can solve the message lossing problem, I prefer to guarantee reliability on transport layer which the TCP protocol promise to do.
I use Writer & IOException in my socket, it works fine. Try this:
public static void sendUTF(String str)
{
try
{
outWriter.write(str + '\n');
outWriter.flush();
}
catch (IOException e)
{
e.printStackTrace();
outServ.setText("Connection lost!");
}
}
public static Writer outWriter = new OutputStreamWriter(outputStream, "UTF-8");
This is a problem with the TCP stack (OS level) and is a problem difficult to solve.
It happens also if the server is the one which lose connection (try to restart your server after opening the socket and no client will notice)... you will suffer a "broken pipe error" next time you send a packet through the socket.
So, there are two scenarios:
1- broken pipe when client sends information.
In this scenario you should capture the IOException and retry to open the connection (you will have to define your retry policies).
2- broken pipe when the server lose connectivity
When the server lose connection the client doesn't notice so, In this scenario you should send packets to the server in a regular basis (polling technique) and try to reconnect just in case the connection is lost.
This is needed just if you receive from the server updates, if you traffic is always client-->server only the scenario 1 applies.

Socket, Read and Write threads

Using socket connection i need to have two threads, one for reading and one for writing. I found other questions about socket connections but I don't understand how i can use the same socket in two different threads.
I have to create a socket in a different thread from the UI thread, so i need to start a thread to create the socket. Where can i start the two threads?
Sample code structure to give you an idea.
public class SocketActivity extends Activity {
Socket s;
OutputStream dout;
String ip = "127.0.0.1";
int port = 8080;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new Thread(new Runnable() {
#Override
public void run() {
try {
s = new Socket(ip, port);
new Thread(new ReaderRunnable(s));
new Thread(new WriteRunnable(s));
} catch (IOException e) {
e.printStackTrace();
//Handle error state
}
}
});
}
// You can put this class outside activity with public scope
class ReaderRunnable implements Runnable {
Socket socket;
public ReaderRunnable(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
if (socket != null && socket.isConnected()) {
try {
OutputStream out = new BufferedOutputStream(socket.getOutputStream());
//Do reader code
} catch (IOException e) {
e.printStackTrace();
}
} else {
//Handle error case
}
}
}
// You can put this class outside activity with public scope
class WriteRunnable implements Runnable {
Socket socket;
public WriteRunnable(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
if (socket != null && socket.isConnected()) {
try {
InputStream out = new BufferedInputStream(socket.getInputStream());
//Do writer code
} catch (IOException e) {
e.printStackTrace();
}
} else {
//Handle error case
}
}
}
}
Judging by your question this is client side. You don't have to use the socket itself in two different threads. For the read thread you use the InputStream of the socket, and for the write thread you use the OutputStream.
That way you don't have to create a seperate thread just for the socket. Both the read and write threads can be started from the UI thread. For creating the threads i refer you to the Android Documentation Processes and Threads.

Categories

Resources