I am trying to create a connection between two applications using android. I have tried to use sockets to connect. I have created two application
One which accepts the connection when client wants to connect
and another application that requests to connect.
I have successfully run this code in same manner in pc in java in pc network. Is the way of connecting to android also same?
My server class implementation
public class MainActivity extends AppCompatActivity {
private Button startButton;
private ServerSocket server;
private Socket connection;
private TextView statusText;
private ObjectOutputStream output;
private ObjectInputStream input;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusText=(TextView)findViewById(R.id.statusText);
startButton=(Button)findViewById(R.id.startButton);
startButton.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
startRunning();
}
}
);
}
private void startRunning() {
try{
server=new ServerSocket(8080);
while(true)
{
try{
waitForConnection();
setUpStreams();
whileChatting();
}catch(Exception e){}
}
} catch(Exception e){}
}
public void waitForConnection()
{
setMyStatus("Waiting for client to connect...");
try {
connection= server.accept();
setMyStatus("Now connected to "+ connection.getInetAddress().getHostName());
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpStreams()
{
try {
output= new ObjectOutputStream(connection.getOutputStream());
output.flush();
input= new ObjectInputStream(connection.getInputStream());
setMyStatus("Streams are now setup. Ready to go...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void whileChatting()
{
setMyStatus("You can now start chatting...");
}
public void setMyStatus(String msg) {
statusText.setText(msg);
}
}
I will use the tasks like async task later. But i am just trying to set up connection in these application.
My client implementation goes like this
public class MainActivity extends AppCompatActivity {
private Button startButton;
private Socket connection;
private TextView statusText;
public ObjectOutputStream output;
public ObjectInputStream input;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
statusText=(TextView)findViewById(R.id.statusText);
startButton=(Button)findViewById(R.id.startButton);
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startRunning();
}
});
}
private void startRunning() {
connectToServer();
setUpStreams();
whileChatting();
}
public void connectToServer()
{
setMyStatus("Connecting to server. Please wait...");
try {
connection= new Socket(InetAddress.getByName("127.0.0.1"),8080);
setMyStatus("Connected to Server."+ connection.getInetAddress().getHostName());
} catch (IOException e) {
e.printStackTrace();
}
}
public void setUpStreams()
{
try {
output= new ObjectOutputStream(connection.getOutputStream());
output.flush();
input= new ObjectInputStream(connection.getInputStream());
setMyStatus("Streams are now setup. Ready to go...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void whileChatting()
{
setMyStatus("You can now start chatting...");
}
public void setMyStatus(String msg) {
statusText.setText(msg);
}
}
The error I got is in the case of client that tries to connect to server
java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.OutputStream java.net.Socket.getOutputStream()' on a null object reference
at com.myapp.client.clientdemo.MainActivity.setUpStreams(MainActivity.java:71)
at com.myapp.client.clientdemo.MainActivity.startRunning(MainActivity.java:46)
at com.myapp.client.clientdemo.MainActivity.access$000(MainActivity.java:16)
at com.myapp.client.clientdemo.MainActivity$1.onClick(MainActivity.java:33)
It's because "connection" was never created. Probably because it failed to connect or it timed out and it moved on to the next code. If it timed out or didn't connect, then you need to catch that exception and retry to connect before moving on with your later code.
Socket can be tricky if you do not catch all the erroneous states they can get into.
simply wrap your try and catch with a while loop until the condition is met like this:
while(!connected & !closed){
try {
connection= new Socket(InetAddress.getByName("127.0.0.1"),8080);
connected = true;
//now it is connected and will exit the loop and continue with other code
} catch (SocketTimeoutException socketTimeoutException) {
//add this for safety
} catch (IOException e) {
e.printStackTrace();
}
}
Related
I'm trying to write a simple client/server program, where the client is an android app and the server is a Raspberry Pi 4. All I want to do is allow the client to type a message and have the Raspberry Pi display the message on the terminal. However, my app keeps throwing an exception at the out.writeObject(message_text) line in the sendMessage() method.
public class MainActivity extends AppCompatActivity {
private EditText message;
private Button send;
private ObjectOutputStream out;
private Socket socket;
private String raspi_ip = "enter ip here";
private int raspi_portnum = 12345;
Client client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
message = findViewById(R.id.message_text);
send = findViewById(R.id.send_button);
try{
client = new Client(raspi_ip,raspi_portnum);
client.start();
} catch (Exception e){
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Error! ").setMessage("Couldn't connect to server.").setNeutralButton("OK", null).create().show();
}
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
client.sendMessage();
}
});
}
private void closeConnection(){
try{
out.close();
socket.close();
} catch (Exception e){
e.printStackTrace();
}
}
#Override
protected void onStop(){
super.onStop();
closeConnection();
}
private class Client extends Thread {
private String ip_address;
private int port_number;
public Client(String ipaddress,int portnum){
this.ip_address = ipaddress;
this.port_number = portnum;
}
#Override
public void run() {
super.run();
connectToServer(ip_address,port_number);
}
public void connectToServer(String ipaddress, int portnum){
try{
socket = new Socket(InetAddress.getByName(ipaddress),portnum);
out = new ObjectOutputStream(socket.getOutputStream());
out.flush();
}catch (Exception e){
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Error! ").setMessage("Couldn't connect to server.").setNeutralButton("OK", null).create().show();
}
}
public void sendMessage(){
String message_text = message.getText().toString();
try{
out.writeObject(message_text);
out.flush();
} catch (Exception e) {
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this);
dialog.setTitle("Error! ").setMessage("IO Exception.").setNeutralButton("OK", null).create().show();
}
}
}
}
Here is the server side java program:
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class RaspPiServer {
private ServerSocket server;
public RaspPiServer(){
}
public static void main(String[] args){
RaspPiServer server = new RaspPiServer();
server.runServer();
}
public void runServer(){
try{
server = new ServerSocket(12345,100);
while (true){
new Controller(server.accept()).start();
}
} catch(Exception e){
e.printStackTrace();
}
}
private class Controller extends Thread {
private Socket socket;
private ObjectInputStream input;
private String in;
public Controller(Socket socket){
this.socket = socket;
System.out.println("New client at " + socket.getRemoteSocketAddress());
}
#Override
public void run(){
try{
input = new ObjectInputStream(socket.getInputStream());
while (!(in = (String)input.readObject()).equals("close")){
System.out.println(in);
}
} catch(Exception e){
e.printStackTrace();
} finally {
closeConnection();
System.out.println("Connection with client # " + socket.getRemoteSocketAddress() + " closed");
}
}
private void closeConnection() {
try {
input.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Is there an easy fix here, or am I missing something bigger?
i am building app which will become server and other 3 or 5 phones become client. and from server i will send code for instruction all device click photo at same time. i am confusing how to do that..i have tcp/udp but it only connect 1 device but i want multiple device.
class MyServer implements Runnable
{
ServerSocket serverSocket;
Socket socket;
DataInputStream dataInputStream;
String msg="";
Handler handler=new Handler();
#Override
public void run() {
try {
serverSocket=new ServerSocket(9700);
while (true)
{
socket=serverSocket.accept();
dataInputStream=new DataInputStream(socket.getInputStream());
msg= dataInputStream.readUTF();
handler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show();
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Backgroundtask extends AsyncTask<String,Void,String>
{
Socket socket;
DataOutputStream dataOutputStream;
String ip,msg;
#Override
protected String doInBackground(String... strings) {
ip=strings[0];
msg=strings[1];
try {
socket=new Socket(ip,9700);
dataOutputStream=new DataOutputStream(socket.getOutputStream());
dataOutputStream.writeUTF(msg);
dataOutputStream.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
i want when i am trigger instruction from server all device must follow at same time.
I am using this code please suggest me any link and any kind of books related to my question. this code is working fine but it is used to send only text after fetching from a textview between two devices using wifi direct.
btnSend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msg=writeMsg.getText().toString();
sendRecieve.write(msg.getBytes());
}
});
public class ServerClas extends Thread{
Socket socket;
ServerSocket serverSocket;
#Override
public void run() {
try{
serverSocket=new ServerSocket(8888);
socket=serverSocket.accept();
sendRecieve=new SendRecieve(socket);
sendRecieve.start();
}catch (IOException e){
e.printStackTrace();
}
}
}
public class SendRecieve extends Thread{
private Socket socket;
private InputStream inputStream;
private OutputStream outputStream;
public SendRecieve(Socket skt){
socket=skt;
try{
inputStream=socket.getInputStream();
outputStream=socket.getOutputStream();
}catch (IOException e){
e.printStackTrace();
}
}
#Override
public void run() {
byte[] buffer=new byte[1024];
int bytes;
while (socket!=null){
try{
bytes=inputStream.read(buffer);
if( bytes>0){
handler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
public void write(byte[] bytes){
try {
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ClientClass extends Thread{
Socket socket;
String hostAdd;
public ClientClass(InetAddress hostAddress){
hostAdd=hostAddress.getHostAddress();
socket=new Socket();
}
#Override
public void run() {
try{
socket.connect(new InetSocketAddress(hostAdd,8888),500);
sendRecieve=new SendRecieve(socket);
sendRecieve.start();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
I think you should use this API
I am creating an android application in which i am creating socket connection in one activity and using Shared Preferences and in another activity I am fetching the socket variables to do furthur jobs but its not working as i am expected
My question is how can i use my exixting socket connection in different actvities i have searched about it Got some terms like singltone class,Aysnc task, But i am not getting it,if singltone is proper way to use socket connetion in different activities then How can i use singlton class in following code please suggest me changes...!!!
Otherwise is it proper way am i doing Shared PRef as following??also suggest some changes!!!
UPDATE: Tagged singlton for suggestions
So here is First Activity
public class ipInfo extends AppCompatActivity {
EditText ipaddress;
String IPADD;
Integer PORT=null;
EditText portnum;
Button connect_btn;
StrictMode.ThreadPolicy policy;
Socket cs = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_ipinfo);
policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
ipaddress = (EditText)findViewById(R.id.editText);
portnum = (EditText)findViewById(R.id.editText2);
connect_btn =(Button)findViewById(R.id.button);
ip_check();
}
public void ip_check(){
connect_btn.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
IPADD=ipaddress.getText().toString();
PORT=Integer.parseInt(portnum.getText().toString());
try { cs = new Socket();
cs.connect(new InetSocketAddress(IPADD, PORT), 2000);
SharedPreferences sharedPreferences = getSharedPreferences("ipstore", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("ipadd",IPADD);
editor.putInt("port",PORT);
editor.commit();
if(cs.isConnected()) {
Toast.makeText(ipInfo.this, "Connected", Toast.LENGTH_SHORT).show();
Intent inst = new Intent(ipInfo.this,homeActivity.class);
startActivity(inst);
finish();
}
}catch (IOException e)
{Toast.makeText(ipInfo.this,"Server is disconnected\n",Toast.LENGTH_SHORT).show();
}catch (Exception e)
{Toast.makeText(ipInfo.this,e.getMessage(),Toast.LENGTH_SHORT).show();}
}
}
);
}
}
from this activity am fetching values in following activity
public class PowerActivity extends AppCompatActivity {
Button restart,shutdown,logof,sleep,abort;
StrictMode.ThreadPolicy policy;
Socket cs = null;
DataOutputStream out=null;
String SERVERIP;
int PORT;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_power);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
restart = (Button)findViewById(R.id.restart);
shutdown = (Button)findViewById(R.id.shutdown);
logof = (Button)findViewById(R.id.logof);
sleep = (Button)findViewById(R.id.sleep);
abort = (Button)findViewById(R.id.abort);
SharedPreferences sharedPreferences=getSharedPreferences("ipstore", Context.MODE_PRIVATE);
SERVERIP =sharedPreferences.getString("ipadd","");
PORT=sharedPreferences.getInt("port", 8002);
Toast.makeText(this,"Working"+SERVERIP+"\n"+PORT,Toast.LENGTH_LONG).show();//this line working fine
policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
remotecmnd();
}
public void remotecmnd(){
restart.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
//restart code
try{
cs = new Socket(SERVERIP,PORT);
try{
out = new DataOutputStream(cs.getOutputStream());
out.writeUTF("restart");
Toast.makeText(PowerActivity.this, "RESTART SUCCESS", Toast.LENGTH_LONG).show();
} catch (Exception ea) {
Toast.makeText(PowerActivity.this, ea.getMessage(), Toast.LENGTH_LONG).show();
}
}catch (IOException e) {
Toast.makeText(PowerActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}
);
}
}
here is server part code
public class serverbackend extends Thread implements Runnable{
public static int SERVERPORT = 8002;
public boolean running = false;
public volatile boolean stop = false;
public Socket client = null;
ServerSocket sc = null;
String value;
public static void main(String[] args) {
mwcobj = new MainWindowController();
}
#Override
public void run() {
super.run();
running = true;
try {
System.out.println("Server Has Started........ \nWaiting for client........");
sc = new ServerSocket(SERVERPORT);
try {
while (!stop && running) {
client = sc.accept();
System.out.println("Connection Accepted......");
DataInputStream dis = new DataInputStream(client.getInputStream());
value = dis.readUTF();
switch (value) {
//Restart the system
case "restart":
System.out.println("Restarting");
Runtime.getRuntime().exec("shutdown -r -t 10");
break;
//some extra code
default:
break;
}
}
} catch (IOException e) {
System.out.println("Inner try catch "+e.getMessage());
}
} catch (IOException e) {
System.out.println("Final try catch error "+e.getMessage());
}
}
public void requestStop(){
try{
stop = true;
sc.close();
System.out.println("Server Has Stopped");
}catch(IOException e){System.out.println("Server Stopped "+e.getMessage());}
}
}
In my opinion, I created a bluetooth communication app,where I get the same problem,
The answer for the this is to use getter and setter methods. It is very easy to set socket and get socket from other java class rather than sending across activities , If I came across other methods I will definitely will tell you on that..
Using getter setter will work for you I beleive.
public class getset
{
static BluetoothSocket sock;
getset(BluetoothSocket sock)
{
this.sock=sock;
}
public static synchronized BluetoothSocket getSock() {
return sock;
}
public static synchronized void setSock(BluetoothSocket sock) {
getset.sock = sock;
}
}
In the place of using shared preference
setSock(socket); //socket is the Bluetoothsocket which you have to save
Bluetoothsocket socket=getSock(); // to get value from the socket
refer https://teamtreehouse.com/community/how-do-you-add-getters-and-setter-in-android-java
I have got huge problem with my Android app and I would like to ask you for help.
I am currently writing Android Clietn-Server app using sockets. I have found lots of tutorils on the Internet and from them I have created basics for my project. However, all tutorials are only for one message send and that's all. I need to send more of them so I've been trying to modify it.
This are code fragments responsible for server and client. The rest is not important at this time.
Server:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
serverStatus = (TextView) findViewById(R.id.server_status);
recivedMsg = (TextView)findViewById(R.id.rec_msg);
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." + System.getProperty("line.separator"));
}
});
try {
line = null;
while (connected) {
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
if((line = in.readLine())!=null)
{
Log.d("ServerActivity", line);
handler.post(new Runnable() {
#Override
public void run() {
if(recivedMsg.equals("CLOSE"))
{
recivedMsg.append("CLOSE socket");
connected = false;
}
else
{
recivedMsg.append("MSG: " + line + System.getProperty("line.separator"));
}
// do whatever you want to the front end
// this is where you can be creative
}
});
}
else
{
recivedMsg.append("empty" + System.getProperty("line.separator"));
}
}
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();
}
}
}
Client
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
serverIp = (EditText) findViewById(R.id.server_ip);
connectPhones = (Button) findViewById(R.id.connect_phones);
sendField = (EditText) findViewById(R.id.send_field);
sendMsg = (Button) findViewById(R.id.msg_send);
connectPhones.setOnClickListener(connectListener);
sendMsg.setOnClickListener(sendMessage);
}
#Override
protected void onStop() {
super.onStop();
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = "CLOSE";
out.write(outMsg);
out.flush();
// make sure you close the socket upon exiting
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private OnClickListener connectListener = new OnClickListener() {
#Override
public void onClick(View v) {
serverIpAddress = serverIp.getText().toString();
runTcpConnection();
sendMessageToServer("Msg");
}
};
private OnClickListener sendMessage = new OnClickListener() {
#Override
public void onClick(View v) {
sendMessageToServer(sendField.getText().toString());
}
};
private void runTcpConnection() {
try {
s = new Socket(serverIpAddress, SERVERPORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = "TCP connecting to " + SERVERPORT + System.getProperty("line.separator");
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
SystemClock.sleep(10);
s.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
};
public void sendMessageToServer(String str) {
try {
s = new Socket(serverIpAddress, SERVERPORT);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
//send output msg
String outMsg = str + System.getProperty("line.separator");
out.write(outMsg);
out.flush();
Log.i("TcpClient", "sent: " + outMsg);
s.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "hello222");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("", "hello4333");
}
}
For now devices connect correctly. Moreover They are sending the first connection messages (those in OnClickListener connectListener). The problem is that when I am trying to send another message using sendMessageToServer it is impossible. Those messages shows only after client activity is destroyed.
Very interesting is that without SystemClock.sleep(10); listener runTcpConnection() behave strange. Only 'Connected.' displays on server.
Can someone tell me what I have to do to be able to send messages normally?
EDIT:
This are things that I have found:
If I am at the connection sending more messages than all are empty (null) and after the second one connection error shows - please reconnect phones
If I am at the connection sending more messages without s.close line in sendMessageToServer only one message is passing through. No error is displayed after it.
The message form runTcpConnection shows always (except when in this function is no SystemClock.sleep(10))
Hope it will help someone to diagnose my error.
As I see, you create a new socket whenever user click button send, right? I recommend you should init it only one time when user click connect, then you use it in send click event ( because this is TCP, you will disconnect to server if you create new instance of socket)
So, you should remove these lines in sendMessageToServer :
s = new Socket(serverIpAddress, SERVERPORT);
s.close();
and this line in runTcpConnection
s.close();
Socket should close whenever you don't want communicate with the server (onstop is an example, or when change activity...)
Also you should create only one instance of BufferedWriter too.
Hope this help.