I am trying to connect to a chat server on the internet from an Android app so first I test whether I have contact with the server from an AsyncTask:
#Override
protected Void doInBackground(SocketAndEditText... soEd) {
try{
InetAddress address1 = InetAddress.getByName("130.237.161.23");
boolean reachable = address1.isReachable(4456);
//...
} catch (Exception e) {
//...
}
}
When I run the above code the variable reachable gets the value false but when I run the same code as a simple Java console application I get true:
import java.net.InetAddress;
public class Test {
public static void main(String[] args) {
try{
InetAddress address1 = InetAddress.getByName("130.237.161.23");
boolean reachable = address1.isReachable(4456);
System.out.println(reachable);
} catch (Exception e) {
//...
}
}
}
In my manifest file I have <uses-permission android:name="android.permission.INTERNET" />
Why does it not work in Android but works as a Java application?
Related
I have developed and Android application with is connecting to JAVA Web Socket and basically it is working very well.
The issue is, that sometimes the client is disconnected but connection at the server side is appearing to be connected.
I try to investigate, when and why it happened but unfortunately i could not find the a specific scenario that cause to this problem.
I have thought to implement Ping/Pong messaging between server and all clients and in case that there is no answer from the clients is to closed the connection at the server side.
i can easily implement such my private mechanism but I have read around and I understand that Java and Android has an build in Ping/Pong messaging mechanism but i was not able to find any example of that.
Can anyway, provide a simple example how to implement Ping/Pong messaging functionality using the build in tools?
I have succeed to implement Ping/Pong functionality between EE JAVA WebSocket and android application. The server is sending Ping message to client every 5 min. if server does not got Pong message back within 5 second, the server is closing client connection.
here is my solution if someone will need it:
WebSocket side:
public class User {
public ScheduledExecutorService pingExecutorService;
public Timer disconnectTimer;
private Session userSession;
private String userName;
public User(Session userSession) {
this.userSession = userSession;
}
public Session getUserSession() {
return userSession;
}
public void setUserSession(Session userSession) {
this.userSession = userSession;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
#OnOpen
public void onOpen(Session session) {
User newUserConnection = new User(session);
connections.getConnections().put(session.getId(), newUserConnection);
schedulePingMessages(newUserConnection);
}
#OnClose
public void onClose(Session session) {
handleOnClose(session);
}
#OnMessage
public void onMessage(String message, Session session) {
messageHandler.handleMessage(message, session);
}
#OnMessage
public void onPong(PongMessage pongMessage, Session session) {
String sourceSessionId = session.getId();
User user = connections.getConnections().get(sourceSessionId);
user.disconnectTimer.cancel();
user.disconnectTimer.purge();
}
#OnError
public void onError(Throwable t) {
System.out.println(new Date() + "onError::" + t.getMessage());
t.printStackTrace();
}
private void schedulePingMessages(User newUserConnection) {
newUserConnection.pingExecutorService = Executors.newScheduledThreadPool(1);
newUserConnection.pingExecutorService.scheduleAtFixedRate(() -> {
scheduleDiconnection(newUserConnection);
try {
String data = "Ping";
ByteBuffer payload = ByteBuffer.wrap(data.getBytes());
newUserConnection.getUserSession().getBasicRemote().sendPing(payload);
} catch (IOException e) {
e.printStackTrace();
}
}, 300, 300, TimeUnit.SECONDS);
}
private void scheduleDiconnection(User user) {
user.disconnectTimer = new Timer();
user.disconnectTimer.schedule(new TimerTask() {
#Override
public void run() {
try {
user.getUserSession().close(new CloseReason(CloseCodes.UNEXPECTED_CONDITION," Client does not response"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}, 5000);
}
The android side just need to add the following override method:
#Override
public void onWebsocketPing(WebSocket conn, Framedata f) {
Log.i("ZCF","got Ping !");
super.onWebsocketPing(conn, f);
}
first of all excuse my english, because i am not good in english. I'm looking for a way to retrieve information in android send from a nodeJS server with socket io. I have the impression that it is a problem of version. my code compiles very well, I do not manage to retrieve the information contained in a JS object.
here is the server code
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var data ={"msg": "hello i am the server"};
io.on('connection',function(socket){
console.log('one user connected '+socket.id);
socket.on('message',function(obj){
console.log(obj.text);
socket.emit('take', data);
})
socket.on('disconnect',function(){
console.log('one user disconnected '+socket.id);
})
})
http.listen(3000,function(){
console.log('server listening on port 3000');
})
the information I'm looking for is 'data'
here is the java code I use, I prefer to put the whole code in case the problem is elsewhere
public class MainActivity extends AppCompatActivity {
private Socket socket;
public String ReceiveMsg ="message par defaut ";
{
try {
socket = IO.socket("http://192.168.43.168:3000");
socket.connect();
} catch (URISyntaxException e) {
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EditText editText = (EditText) findViewById(R.id.editText);
TextView textView = (TextView) findViewById(R.id.textView);
Button but = (Button) findViewById(R.id.button);
socket.connect();
String msg = takemsg(editText);
sendMsg(msg);
socket.on("take", handleIncomingMessages);
textView.setText(getAz(ReceiveMsg));
}
public String takemsg(EditText editText){
String msg = "message par defaut ";
msg = editText.getText().toString();
return msg;
}
public void sendMsg(String msg ){
JSONObject obj = new JSONObject();
try{
obj.put("text", msg);
socket.emit("message", obj);
}catch (JSONException e){
}
}
private Emitter.Listener handleIncomingMessages = new Emitter.Listener(){
#Override
public void call(final Object... args){
runOnUiThread(new Runnable() {
#Override
public void run() {
JSONObject data = (JSONObject) args[0];
try {
ReceiveMsg = data.getString("msg");
} catch (JSONException e) {
}
}
});
}
};
}
First I think we need more data.
What are the outputs of the server? Is connecting well?, check if your code in android is running.
If it's not connecting try setting the port with opts
...
try {
IO.Options opts = IO.Options();
opts.port = 3000;
socket = IO.socket("http://192.168.43.168", opts);
socket.connect();
} catch (URISyntaxException e) {
...
check if your service is alive. for services exists some returns that allows to maintain your service working.
https://developer.android.com/reference/android/app/Service.html#START_STICKY
we must put in the manifest
<uses-permission android:name="android.permission.INTERNET" />
to allow the application to use the network
I'm developing a game using libGdx and Kryonet and I'm currently working on the server <-> android connection.
First I run the server on a computer, and if I run two instances of the program on the same computer (so the IP will be the local IP: "127.0.0.1"), I don't get any problems, and the connection works fine.
But if instead of running the game on desktop, I run it on the android device, the connection doesn't happen. Both the devices are connected to the same Wi-fi network, so to discover the IP, what I do is type "ipconfig" on the console, and check the line that says: "IPv4 Adress" under "Wireles LAN adapter Wi-Fi" (I think it's this one).
I've added this 3 lines to the android manifest file (are they really needed?):
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Here's the important error log:
Do I need to do anything on the device some extra code for the android connection to establish? More permissions perhaps?
Here's the relevant code:
MPServer:
public class MPServer {
Server server;
Array<PlayerInfo> playersInfo;
int numNewPlayers;
public MPServer() throws IOException {
numNewPlayers = 0;
playersInfo = new Array<PlayerInfo>();
server = new Server();
Network.registerPackets(server);
addListeners();
server.bind(Network.PORT);
server.start();
}
private void addListeners() {
server.addListener(new Listener() {
#Override
public void connected(Connection connection) {
}
#Override
public void disconnected(Connection connection) {
}
#Override
public void received(Connection c, Object object) {
}
});
}
public static void main(String[] args) {
try {
new MPServer();
Log.set(Log.LEVEL_DEBUG);
} catch (IOException e) {
e.printStackTrace();
}
}
}
MPClient:
public class MPClient {
static final int TIME_OUT = 5000;
Client client;
MultiPlayMatch match;
public MPClient(String name, int team, MultiPlayMatch match) {
this.match = match;
client = new Client();
client.start();
Network.registerPackets(client);
addListeners();
try {
client.connect(15000, Network.WIFI_IP, Network.PORT);
} catch (IOException e) {
e.printStackTrace();
client.stop();
}
while(true) {
}
}
private void addListeners() {
client.addListener(new Listener.ThreadedListener(new Listener() {
#Override
public void connected(Connection connection) {
}
#Override
public void disconnected(Connection connection) {
}
#Override
public void received(Connection connection, Object object) {
}
}));
}
}
If you are using Windows OS , the reason might be windows firewall, try disabling it if you want to connect your mobile to the local server.
I am basically trying to send a message from my android to my server and the server to send back a response to my android app. I followed THIS tutorial.
Just a simple exercise to introduce myself in to SignalR using Azure Web API and Android.
My Complete Server code in C#:
public class TestHub: Hub {
public void SendMessage(string name, string message) {
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
public void SendClientMessage(CustomType obj) {
Clients.All.broadcastMessage("From Server", "Server got the message bro");
}
public class CustomType {
public string Name;
public int Id;
}
}
Complete Android Java code:
public class MainActivity extends AppCompatActivity {
Handler handler;
TextView statustext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
statustext = (TextView) findViewById(R.id.status);
Platform.loadPlatformComponent(new AndroidPlatformComponent());
// Change to the IP address and matching port of your SignalR server.
String host = "https://My-Service-name.azure-mobile.net/";
HubConnection connection = new HubConnection(host);
HubProxy hub = connection.createHubProxy("TestHub");
SignalRFuture < Void > awaitConnection = connection.start();
try {
awaitConnection.get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
hub.subscribe(this);
try {
hub.invoke("SendMessage", "Client", "Hello Server!").get();
hub.invoke("SendClientMessage",
new CustomType() {
{
Name = "Android Homie";
Id = 42;
}
}).get();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
//I have no idea what the following method is for. Just followed the tutorial.. (blindly)
public void UpdateStatus(String status) {
final String fStatus = status;
handler.post(new Runnable() {
#Override
public void run() {
statustext.setText(fStatus);
}
});
}
public class CustomType {
public String Name;
public int Id;
}
}
Problems with this:
1. I get an exception:
java.util.concurrent.ExecutionException:
microsoft.aspnet.signalr.client.transport.NegotiationException: There
was a problem in the negotiation with the server
2. I feel like I haven't properly called the server from the Java code.
Should the URL be:
https://My-Service-name.azure-mobile.net/
or
https://My-Service-name.azure-mobile.net/api/signalr
Can someone clarify these doubts and help me set it up?
I want to call a stored procedure from sql server to operate a login page
but keep getting this error:
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Sp
{
public static void main(String[] args)
{
String dbName = "My_database";
String serverip="192.168.5.10";
String serverport="1433";
String url = "jdbc:sqlserver://"+serverip+"\\SQLEXPRESS:"+serverport+";databaseName="+dbName+"";
try
{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
}
catch(ClassNotFoundException ex)
{
ex.printStackTrace();
}
Connection con=null;
CallableStatement cstmt=null;
try
{
String databaseUserName = "sa";
String databasePassword = "a123";
con= DriverManager.getConnection(url, databaseUserName, databasePassword);
cstmt=con.prepareCall("{? = call spLoginvalidate(#CO_ID)}");//called the procedure
//how to create procedure had writen in bellow
cstmt.executeUpdate();
System.out.println("done");
}
catch(SQLException ex)
{
ex.printStackTrace();
}
finally
{
try
{
if(cstmt!=null) //close the callablestatement
{
cstmt.close();
cstmt=null;
}
}
catch(SQLException ex)
{
ex.printStackTrace();
}
try
{
if(cstmt!=null) //close the connection
{
cstmt.close();
cstmt=null;
}
}
catch(SQLException ex)
{
ex.printStackTrace();
}
}
}
}
My error message is:
com.microsoft.sqlserver.jdbc.SQLServerException: The value is not set for the parameter number 1.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:190)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.buildParamTypeDefinitions(SQLServerPreparedStatement.java:260)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.buildPreparedStrings(SQLServerPreparedStatement.java:219)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doPrepExec(SQLServerPreparedStatement.java:612)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:400)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:350)
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:180)
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:155)
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeUpdate(SQLServerPreparedStatement.java:314)
at com.first.mainapp.Sp.main(Sp.java:45)
What needs to be done if I want to use the stored procedure to validate a login
Instead of
cstmt=con.prepareCall("{? = call spLoginvalidate(#CO_ID)}");//called the procedure
try
cstmt=con.prepareCall("{EXEC ? = spLoginvalidate(?)}");//called the procedure
cs.registerOutParameter(1, Types.INT);
cs.setInt(2, 1000);//your #CO_ID value here
More information you can get here: http://www.xyzws.com/javafaq/how-to-call-a-stored-procedure-by-jdbc-java-class/169
SQL Server does not know the call statement. Use EXEC instead.