I set up a very basic node.js server with the following code:
const express = require("express");
const app = express();
const port = 8000;
const ip = '192.16x.xxx.yyy'; // the x's and y's are placeholders. I didnt want to write my real IP here
const http = require("http").createServer();
const io = require("socket.io")(http);
// using the socket, we can send/receive data to/from the client
// the server listens for the "connection" event
io.on("connection", (socket) => {
// emit an event called "welcome" with a string as data to the client using its socket
// so, whenever the client connects to the server, it receives this welcome message
socket.emit("welcome", "Hello and Welcome to the Socket.io server.");
console.log("a new client is connected.")
});
// the server listens on the specified port for incoming events
http.listen(port, ip, () => {
console.log("Server is listening on " + ip + ":" + port);
});
So, the server is listening for the "connection" event and sends a welcome message when a client connects to the server.
The client which is an Android app looks like this:
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;
import com.github.nkzawa.emitter.Emitter;
import java.net.URISyntaxException;
public class MainActivity extends AppCompatActivity {
private Socket mSocket;
private TextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = findViewById(R.id.textView);
try {
/*
* IO.socket() returns a socket for the specified URL and port with the
* default options. Notice that the method caches the result, so you can
* always get a same Socket instance for an url from any Activity or
* Fragment.
* */
mSocket = IO.socket("http://192.16x.xxx.yyy:8000");
} catch (URISyntaxException e) {
e.getMessage();
}
/*
* We then can make the socket listen an event on onCreate lifecycle callback.
* */
mSocket.on("welcome", onNewMessage);
/*
* And we explicitly call "connect()" to establish the connection here.
* In this app, we use onCreate lifecycle callback for that, but it
* actually depends on your application.
* */
mSocket.connect();
}
private Emitter.Listener onNewMessage = new Emitter.Listener() {
#Override
public void call(final Object... args) {
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
String message = (String) args[0];
mTextView.setText("Received from Server: " + message);
}
});
}
};
/*
* Since an Android Activity has its own lifecycle, we should carefully manage the
* state of the socket also to avoid problems like memory leaks. In this app, we’ll
* close the socket connection and remove all listeners on onDestroy callback of
* Activity.
* */
#Override
protected void onDestroy() {
// socket gets disconnected
mSocket.disconnect();
// off() removes the listener of the "welcome" event
mSocket.off("welcome", onNewMessage);
super.onDestroy();
}
}
The client code is also very simple: It connects to the server and displays the message it gets from the server.
I got this ex. from the official Socket.IO website at https://socket.io/blog/native-socket-io-and-android/.
When I start the server with node server.js on the terminal of my laptop and use an Android emulator, then everything works fine.
But when I connect my real Android device to my laptop using a USB then the connection does not take place.
Why Android app (running within the real device) does not connect to the server ?
This worked for me: I created a socket with the IP 0.0.0.0, You should Change your IP at your node.js to this value.
Than i opened cmd and entered ipconfig to see what my ip adress is, this is your local IP adress. In the Code i am connecting to this IP Adress.
For example if you see IP 192.168.178.50 in your ipconfig you Change your Android Code to
mSocket = IO.socket("http://192.168.178.50:8000");
And your Node.js Code should look like
const ip = '0.0.0.0';
And dont Forget to Restart your Server when you changed the node.js code
Related
I have trouble with connecting to a local web interface (192.168.10.13:3671) that are connected to my KNX network from the emulator/phone in Android Studio.
I've tried to connect to the same web interface with a already developed app called KNXwizard and that works, but I see in the code that that app uses AsyncTask.
Always getting this error: Error creating KNXnet/IP tunneling link: tuwien.auto.calimero.KNXException: connecting from /192.168.163.198:3671 to /192.168.10.13:3671: socket failed: EPERM (Operation not permitted)
I've checked this posts
Socket failed 1
Socket failed 2
Tried everything there, added permissions to my AndroidManifest.xml, uninstalled, used physical phone etc. But nothing works.
It could be my code, I've tried searching for an alternative method for AsyncTask. So it could be that the code is written wrong. Hope someone could help me out.
MainActivity:
public class MainActivity extends AppCompatActivity {
private static InetSocketAddress local = new InetSocketAddress("192.168.163.198", 3671);
private static InetSocketAddress server = new InetSocketAddress("192.168.10.13",
KNXnetIPConnection.DEFAULT_PORT);
Button btn;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button)findViewById(R.id.button);
ExecutorService executorService = Executors.newSingleThreadExecutor();
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
executorService.execute(new Runnable() {
#Override
public void run() {
//doInBackground
System.out.println("This example establishes a tunneling connection to the KNXnet/IP server " + server);
// A KNX tunneling link supports NAT (Network Address Translation) if required.
// We also indicate that the KNX installation uses twisted-pair (TP) medium, with TP1 being the most common.
// KNXNetworkLink is the base interface implemented by all supported Calimero links to a KNX network.
try (KNXNetworkLink knxLink = KNXNetworkLinkIP.newTunnelingLink(local, server, false, TPSettings.TP1)) {
System.out.println("Connection established to server " + knxLink.getName());
System.out.println("Close connection again");
} catch (KNXException | InterruptedException e) {
// KNXException: all Calimero-specific checked exceptions are subtypes of KNXException
// InterruptedException: longer tasks that might block are interruptible, e.g., connection procedures. In
// such case, an instance of InterruptedException is thrown.
// If a task got interrupted, Calimero will clean up its internal state and resources accordingly.
// Any deviation of such behavior, e.g., where not feasible, is documented in the Calimero API.
System.out.println("Error creating KNXnet/IP tunneling link: " + e);
}
}
});
}
});
}
I figured it out.
It was a stupid mistake with the IP address, should have seen that before. I just change the IP address to that I have on the phone I was connected to (192.168.10.15).
I've taken every step described here in Fiddler site for capturing my application (running in emulator) network packets. The strange thing is that I can decode http/https sent from browser but not https packets from my app. It's more interesting that requests get successful responses! Any idea what might be the problem?
I'm completely stocked and have no idea what should I have done which didn't.
First topic, that I've found on Xamarin forum was Why can't Fiddler detect traffic from Xamarin apps?. The answer is to set DefaultWebProxy:
public override void OnCreate()
{
// get IP from fiddler's internet icon at the top right, or via ipconfig for VirtualBox used by Genymotion
WebRequest.DefaultWebProxy = new WebProxy("192.168.56.1", 8888);
base.OnCreate();
...
}
I put it in MainActivity, but it didn't solve my problem.
Which helped me is Debugging HttpClient Calls with fiddler in PCL:
You will need to change your code to use a HttpClientHandler and a proxy
HttpClientHandler handler = new HttpClientHandler ()
{
Proxy = new WebProxy (new Uri("http://[Computer IP]:[Fiddler port number]")),
UseProxy = true
};
using (var client = new HttpClient(handler))
{
// Make your call in here
}
Looks simple enough only PCLs dont include the Web proxy class in its bundled System.Net dll for whatever reason so you will need to write your own by extending the System.Net.IWebProxy interface
like so
public class WebProxy : System.Net.IWebProxy
{
public System.Net.ICredentials Credentials
{
get;
set;
}
private readonly Uri _proxyUri;
public WebProxy(Uri proxyUri)
{
_proxyUri = proxyUri;
}
public Uri GetProxy(Uri destination)
{
return _proxyUri;
}
public bool IsBypassed(Uri host)
{
return false;
}
}
After all this stuff, I was able to capture requests from my Xamarin.Forms app on Android Emulator.
I am using Twilio android client. device.connect() is working fine but can't able to disconnect the connected call, though the user (I dialed to) if hangup then the call will be disconnected. I have tried with device.disconnectAll() and connection.disconnect(), both are not working. Please guide me wher i'm wrong.
Simple:
Caller can't be able to disconnect the call while callee can.
Thank in Advance.
To connect the call
HashMap<String, String> p = new HashMap<String, String>();
p.put("PhoneNumber", personToCall);
p.put(Connection.IncomingParameterFromKey, (String) device.getCapabilities().get(Device.Capability.CLIENT_NAME));
p.put(Connection.IncomingParameterToKey, personToCall);
device.connect(p, this);
and to disconnect
connection.disconnect()
It's not clear in your code how you're obtaining the connection object, which is one of two pivotal pieces of the Twilio client.
The Twilio Client documentation has an example on making outbound calls:
import com.twilio.client.Connection;
import com.twilio.client.Device;
import com.twilio.client.Twilio;
public class MonkeyPhone implements Twilio.InitListener
{
private Device device;
private Connection connection;
/* ... other methods ... */
public void connect()
{
connection = device.connect(null /* parameters */, null /* ConnectionListener */);
if (connection == null)
Log.w(TAG, "Failed to create new connection");
}
#Override
protected void finalize()
{
if (connection != null)
connection.disconnect();
if (device != null)
device.release();
}
}
In the example, when you call device.connect(), a connection object is returned and stored as a property in the object so it can be referenced again later on. In the finalize method, we call connection.disconnect() to terminate the call.
If you're not calling disconnect on the connection object returned from device.connect() the call may not disconnect properly. See the Twilio documentation for Device.connect for more details.
I connect to the node server with socketio.SocketIO running as a service.And, When Service restarts,opens socket.io without socket.io closure.That's a problem.
A device making multiple socketIO connection on the server side.So the server is swelling..
! I am using gottox/socketio-java-client on android.
Check Socket is connected or not using socket.isConnected().
This will return true if socket is connected
Its just an idea so i don't know the limitations. pls let me know.
You can ping the server to check if the connection is alive.
In android
socket.emit("ping","ping");
socket.on("pong",pingHandler); //EmitterListener
private Emitter.Listener pingHandler=new Emitter.Listener(){
#Override
public void call(final Object... args) {
Log.d("SocketStatus","Connection is active");
});
}
and make the server return response for the ping
socket.on("ping",function(data){
socket.emit("pong","pong"); //from your server ex.Node.js
});
You can check the socket.connected property:
var socket = io.connect();
console.log('Connected status before onConnect', socket.socket.connected);
socket.on('connect', function() {
console.log('Connected status onConnect', socket.socket.connected);
});
It's updated dynamically, if the connection is lost it'll be set to false until the client picks up the connection again. So easy to check for with setInterval or something like that.
Another solution would be to catch disconnect events and track the status yourself.
The following is an expansion/modification of Rafique Mohammed answer above. The correct way is to try to reconnect on client side.
Internet drops (server cannot communicate disconnection to client). Server crashes (server may/may not be able to tell client. Server Restart (server can tell but that just extra work). After reconnection you will also like to rejoin the room for seamless communication
public void connectAfterDisconnectSocket(String senderActivity) {
new Timer().scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
boolean isConnected = false;
isConnected = mSocket != null && mSocket.connected();
if (!isConnected) {
SocketIOClient socketIOClient = new SocketIOClient();
socketIOClient.connectToSocketIO();
if (senderActivity.equals("A")) {
A.joinChatRoom(room);
}
if (senderActivity.equals("B")) {
B.joinChatRoom(room);
}
}
}
}, 0, 1000); //put here time 1000 milliseconds=1 second
}
Dont get angry on me please. I have two questions, I think on very similar theme, so I decided to merge them into one. I have my app on android that is using sensors to do some calculations. I am storing there sesults in my database. What i want to do is to send my data from my phone to my desktop app also with a database (on button click).
To be more precise, here is an example: My light sensor reads current light intensity. Lets say it is 1000lux. Now, when I click my button "Send" in my android app, it will send this value to my desktop apps database. That desktop app will read that value and will show it to user.
Is it possible via WIFI? or better via web, so i will not be limited with distance?
How can android manage this kind of communication?
And my second question is, if controlling media player on my PC is similar to what i said.
EDIT:
I did some research and found one Socket tutorial. I tried it exactly like it is there. So i have this in my android app:
public class Client extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
Client myCli = new Client();
try {
myCli.run();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_client, menu);
return true;
}
public void run() throws Exception {
Socket mySkt = new Socket("192.168.1.6", 9999);
PrintStream myPS = new PrintStream(mySkt.getOutputStream());
myPS.println("Hello server");
BufferedReader myBR = new BufferedReader
(new InputStreamReader(mySkt.getInputStream()));
}
}
and this in netBeans:
//Author: WarLordTech
//Website: http://www.youtube.com/user/WarLordTech
import java.io.*;
import java.net.*;
public class Server {
public static void main(String[] args) throws Exception{
Server myServ = new Server();
myServ.run();
}
public void run() throws Exception{
ServerSocket mySS = new ServerSocket(9999);
Socket SS_accept = mySS.accept();
BufferedReader SS_BF= new BufferedReader(new InputStreamReader
(SS_accept.getInputStream()));
String temp = SS_BF.readLine();
System.out.println(temp);
if (temp!=null) {
PrintStream SSPS = new PrintStream(SS_accept.getOutputStream());
SSPS.println("Got something");
}
}
}
It still isnt workiong. Do I have to set up my network somehow?
You could do it using TCP Sockets. Many languages have implementations for Socket programming so you would "need" to program your desktop app in Java (of course that is always possible!).
Socket Tutorial in Java
This would work over the net and local wifi. You could use other methods for local wifi such as a UDP connection. You'd need to setup a TCP server and make sure you had access etc.
There may be other ways to do this but it's not such a trivial task to do!