I don't know what happen with my source code about Socket in Android, when I use method
.isConnected()
My app always force close. And here my source code
public class MyActivity extends Activity {
private String IP;
private int PORT;
private Socket socket;
private PrintWriter printWriter;
private TextView text;
private EditText fieldIp;
private EditText fieldPort;
private Button connect;
private FrameLayout frameIP;
private String message;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
frameIP = (FrameLayout)findViewById(R.id.frameIP);
connect = (Button)findViewById(R.id.connect);
fieldIp = (EditText)findViewById(R.id.ip);
fieldPort = (EditText)findViewById(R.id.port);
text = (TextView)findViewById(R.id.keterangan);
connect.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
IP = fieldIp.getText().toString();
PORT = Integer.parseInt(fieldPort.getText().toString());
SocketConnect socketConnect = new SocketConnect(IP,PORT);
socketConnect.execute();
}
});
}
private class SocketConnect extends AsyncTask<Void, Void, Boolean> {
String ip;
int port;
public SocketConnect(String a, int b){
this.ip = a;
this.port = b;
}
#Override
protected Boolean doInBackground(Void... params) {
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ip,port));
if(socket.isConnected())
{
text.setText("Connected!");
}
else
{
text.setText("Failed to connect!");
}
} catch (IOException e) {
Log.e("MyActivity",e.getMessage());
}
finally {
startActivity(new Intent(getApplicationContext(),ListViewText.class));
}
return null;
}
}
}
And I use this in AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
I hope you can help me guys :(
Change the doInBackground method as follows...
#Override
protected Boolean doInBackground(Void... params) {
boolean success = true;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(ip, port));
} catch (Exception e) {
success = false;
Log.e("MyActivity", e.getMessage());
}
return success;
}
Then add an onPostExecute method...
#Override
protected void onPostExecute(boolean result) {
if(result) {
text.setText("Connected!");
startActivity(new Intent(MyActivity.this, ListViewText.class));
}
else {
text.setText("Failed to connect!");
}
}
First thing you are calling UI operation outside of UI thread (that is why AsyncTask was created, to handle background job only in doInBackground) So problem about displaying text un TextView is solved...
But more important thing:
Never open Socket in AsyncTask. On Android developer site you can find following:
If you need to keep threads running for long periods of time, it is
highly recommended you use the various APIs provided by the
java.util.concurrent package such as Executor, ThreadPoolExecutor and
FutureTask.)
And that is exactly what you want to do. So use Service, Thread or those mentioned above instead.
Related
I need help to understand how to make a connection to a tcp client on Android with a server, the connection itself is not the problem, but rather the exchange between the activities.
I will try to explain with the attached image.
I need to start a connection to a server using TCP / IP sockets. After a search for the net I found several examples, but all using a single activity, but I need it to work as follows:
1 - Let's say in the main activity I start the connection by clicking on CONNECT.
2 - But then I need to click the ACTIVITY_A button to open another activity while keeping the connection that has already been opened in the main activity, and continue sending and receiving information in its ACTIVITY_A.
3 - Back to ACTIVITY_A, click on ACTIVITY_B doing the same process above.
I am lost between which solution to use and how to use, asynctask, thread, singleton, intent, context.
You can use Android Service for network connectivity. Also please look at Android Networking official doc. Also there are a lot library for performing network requests (like Robospice)
I edited the previous message to inform how I solved it, it may not be ideal but it is working.
Act_Main
public class Act_Main extends AppCompatActivity implements Singleton.OnReceiveListener{
private Singleton sing;
String ip = "192.168.4.1";
int porta = 23;
Button btConectar, btActivityA, btActivityB;
TextView txtStatus;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_main);
btConectar = (Button) findViewById(R.id.btConectarID);
btActivityA = (Button) findViewById(R.id.btActivityAID);
btActivityB = (Button) findViewById(R.id.btActivityBID);
txtStatus = (TextView) findViewById(R.id.txtStatusID);
}
public void conectar (View view){
sing = Singleton.getInstance(ip, porta, this);
}
public void openActivityA(View view) {
Intent it = new Intent(Act_Main.this, Activity_A.class);
startActivity(it);
}
public void openActivityB(View view) {
Intent it = new Intent(Act_Main.this, Activity_B.class);
startActivity(it);
}
#Override
public void onReceive(String dataRx) {
// Trata a informação recebida aqui.
txtStatus.setText(dataRx);
}
}
Singleton
public class Singleton {
private static Singleton instancia = null;
private static OnReceiveListener orl = null;
private boolean running;
private static Client client;
private Singleton() {
}
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
public static interface OnReceiveListener {
public void onReceive(String dataRx);
}
public static Singleton getInstance(String _ip, int _port, OnReceiveListener listener) {
if (instancia == null) {
client = new Client(_ip, _port);
client.execute();
instancia = new Singleton();
}
orl = listener;
return instancia;
}
public void sendMsg(String str) {
client.sendMessage(str);
}
private static class Client extends AsyncTask<Void, String, Void> {
String dstAddress;
int dstPort;
String response = "";
BufferedReader in;
PrintWriter out;
String incomingMessage;
private boolean running;
Client(String addr, int port) {
dstAddress = addr;
dstPort = port;
}
#Override
protected Void doInBackground(Void... arg0) {
Socket socket = null;
try {
socket = new Socket(dstAddress, dstPort);
running = true;
// Cria um objeto PrintWriter para enviar mensagens ao servidor.
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
// Cria um objeto BufferedReader para receber mensagens do servidor.
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Log.d(TAG, "In/Out created");
while (running) {
incomingMessage = in.readLine();
if (incomingMessage != null) {
publishProgress(incomingMessage);
}else{
running = false;
}
incomingMessage = null;
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null) {
out.close();
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
#Override
protected void onProgressUpdate(String... params) {
orl.onReceive(params[0]);
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
}
private void sendMessage(String message) {
if (out != null && !out.checkError()) {
out.println(message);
out.flush();
Log.d(TAG, "Sent Message: " + message);
}
}
}
}
Activity_A
public class Activity_A extends AppCompatActivity implements Singleton.OnReceiveListener {
private Singleton sing;
String ip = "192.168.4.1";
int porta = 23;
Button btVoltar, btEnviar;
TextView txtRx, txtTx;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_a);
btEnviar = (Button) findViewById(R.id.btEnviarID);
btVoltar = (Button) findViewById(R.id.btVoltarID);
txtRx = (TextView) findViewById(R.id.txtRxID);
txtTx = (TextView) findViewById(R.id.txtTxID);
sing = Singleton.getInstance(ip, porta, this);
}
#Override
public void onReceive(String dataRx) {
txtRx.setText(dataRx);
}
public void Enviar (View view){
sing.sendMsg(txtTx.getText().toString());
}
public void Voltar(View view) {
this.finish();
}
}
Activity_B
public class Activity_B extends AppCompatActivity implements Singleton.OnReceiveListener {
private Singleton sing;
String ip = "192.168.4.1";
int porta = 23;
Button btVoltar, btEnviar;
TextView txtRx, txtTx;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
btEnviar = (Button) findViewById(R.id.btEnviarID);
btVoltar = (Button) findViewById(R.id.btVoltarID);
txtRx = (TextView) findViewById(R.id.txtRxID);
txtTx = (TextView) findViewById(R.id.txtTxID);
sing = Singleton.getInstance(ip, porta, this);
}
#Override
public void onReceive(String dataRx) {
txtRx.setText(dataRx);
}
public void Enviar (View view){
sing.sendMsg(txtTx.getText().toString());
}
public void Voltar(View view) {
this.finish();
}
}
Evidently it is not finished, but it is a beginning.
Thank you to those who have responded.
I'm trying to develop an android app with remote access functions. I have been searching similar posts about how remote desktop is made and what is the most efficient method, but i haven't found too mutch information about this.
Now i'm trying to send screenshots and display each one on a ImageView. It works, but the ImageView doesn't get refreshed until the app has ended. I tried to use postInvalidate() and invalidate() on an AsyncTask, but it didn't work.
I'd also like to know if there is a better way (or even different ways) to develop a remote desktop app. I wanna do it by myself, so i don't want to use any app as TeamViewer or similar.
Thanks for the help. Here is my code:
Client
public class MainActivity extends Activity {
static Button boton;
static byte[] imagen;
static ImageView imagenVista;
static Bitmap bmp;
static Socket clientSocket;
static OutputStream os;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
boton = (Button)findViewById(R.id.button1);
boton.setOnClickListener(evento);
imagenVista = (ImageView)findViewById(R.id.imageView1);
}
private OnClickListener evento = new OnClickListener() {
#TargetApi(Build.VERSION_CODES.GINGERBREAD)
#Override
public void onClick(View v) {
if (boton.getText().equals("Start")){
boton.setText("Stop");
try{
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
while(true){
Socket clientSocket= new Socket();
InetSocketAddress addr=new InetSocketAddress("10.209.0.93", 5555);
clientSocket.connect(addr);
OutputStream os=clientSocket.getOutputStream();
os.write("capture".getBytes());
ObjectInputStream entrada = new ObjectInputStream(clientSocket.getInputStream());
construyendo_img(entrada)
new TareaSegundoPlano().doInBackground(entrada);
entrada.close();
os.flush();
clientSocket.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
else{
boton.setText("Start");
}
}
};
public void construyendo_img(ObjectInputStream entrada)throws IOException, ClassNotFoundException{
byte[] bytes_img = (byte[]) entrada.readObject();
ByteArrayInputStream entrada_img = new ByteArrayInputStream(bytes_img);
bmp = BitmapFactory.decodeByteArray(bytes_img, 0, bytes_img.length);
imagenVista.setImageBitmap(bmp);
}
public class TareaSegundoPlano extends AsyncTask<Void, ObjectInputStream, Void>{
protected void onPreExecute(){}
protected Void doInBackground(ObjectInputStream... params) {
imagenVista.invalidate();
return null;
}
protected void onProgressUpdate(Void... values) {}
protected void onPostExecute(Void result){}
#Override
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
return null;
}
}
}
I'm try to writing an online game with a socket connection.
So I use asynctask to make a socket connection.
SocketServer.java
public class SocketServer{
private MyCustomListener listener;
private String ip = "127.0.0.1";
private int port = 4444;
#SuppressWarnings("unused")
private Context context;
private SocketAsync socketAsync;
private String dataInput, username;
public SocketServer(Context context) {
this.context = context;
}
public void setOnRecieveMsgListener(MyCustomListener listener) {
this.listener = listener;
}
public void connect() {
socketAsync = new SocketAsync();
socketAsync.execute();
}
public void sentData(String x, String y, String z) {
dataInput = null;
JSONObject object = new JSONObject();
// JSON Encode
socketAsync.sentJSON(object);
}
private class SocketAsync extends AsyncTask<Void, Void, String> {
private Socket socket;
private PrintWriter printWriter;
#Override
protected String doInBackground(Void... params) {
try {
socket = new Socket(InetAddress.getByName(ip),port);
OutputStreamWriter streamOut = new OutputStreamWriter(socket.getOutputStream(), "UTF-8");
printWriter = new PrintWriter(streamOut);
streamOut.flush();
BufferedReader streamIn = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
Looper.prepare();
while(socket.isConnected()) {
try {
dataInput = streamIn.readLine();
listener.onRecieveMessage(new MyListener(dataInput));
}
catch(Exception e) {}
}
Looper.loop();
}
catch(Exception e) {}
return null;
}
public void sentJSON(JSONObject object) {
if(socket.isConnected()) {
try {
printWriter.println(object.toString());
printWriter.flush();
}
catch(Exception e) {}
}
}
}
}
Login.class
public class Login extends Activity implements MyCustomListener {
JSONObject object;
SocketServer socketserver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
socketserver = new SocketServer(this);
socketserver.setOnRecieveMsgListener(this);
socketserver.connect();
button();
}
private void button() {
Button loginBt = (Button)findViewById(R.id.login_bt);
final EditText un = (EditText)findViewById(R.id.username);
final EditText ps = (EditText)findViewById(R.id.password);
final String[] logindata = new String[2];
loginBt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
logindata[0] = un.getText().toString();
logindata[1] = ps.getText().toString();
socketserver.setUsername(logindata[0]);
socketserver.sentData("SERVER", "TEST", "login");
}
});
}
private void toMainScreen() {
Intent x = new Intent(this,Main.class);
startActivity(x);
}
#Override
public void onRecieveMessage(MyListener ml) {
try {
JSONObject json = new JSONObject(ml.getMsgStr());
System.out.println(json.getString("content"));
if(json.getString("content").equals("TRUE")) {
toMainScreen();
}
else
Toast.makeText(getApplicationContext(), "Login Fail", Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
Log.e("## JSON DECODE", e.toString());
e.printStackTrace();
}
}
}
Main.class
public class Main extends Activity implements MyCustomListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//do some thing
}
#Override
public void onRecieveMessage(MyListener ml) {
System.out.println("MAIN : " + ml.getMsgStr());
}
}
so how can I pass object "socketserver" from login class to main class?
or is there an other way to do something like this?
sorry for my poor english.
You should not try to pass an instance of SocketServer around. One of it's properties is context which means you should not used it outside the original context it was created in (i.e. activity it was created in) or you'll have memory leaks.
Your SocketServer class needs IP and port. This is the kind of information that you should pass between activities and then use that to create another instance of your SocketServer class.
I'm trying to write a server/client app in android using sockets and i handle the client socket in AsyncTask (server is not android, just ordinary java).I get the exception when I'm trying to read from the server.I found out that when I delete android:targetSdkVersion="16" from android manifest the exception goes away and I can read from the server.
I don't understand why is that? could anyone help me clarify this? I also have problems understanding how the asynctask method doInBackground and my own methods relate. Does conhandler.execute() run doInBackground() and then just waits until I call the other methods? thanks for help.
public class ConnectionHandler extends AsyncTask<Void, Void, Void>{
public static String serverip = "10.0.2.2";
public static int serverport = 5000;
Socket s;
PrintWriter out;
BufferedReader in;
protected Void doInBackground(Void... params) {
try {
s = new Socket(serverip, serverport);
Log.i("AsyncTank", "doInBackgoung: Created Socket");
}...
if (s.isConnected()) {
try {
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
out = new PrintWriter(s.getOutputStream(), true);
Log.i("AsyncTank", "doInBackgoung: Socket created, Streams assigned");
} ....
}
public void writeToStream(String message) {
try {
if (s.isConnected()){
out.println(message);
} else {
Log.i("AsynkTask", "writeToStream : Cannot write to stream, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "writeToStream : Writing failed");
}
}
public String readFromStream() {
try {
if (s.isConnected()) {
Log.i("AsynkTask", "readFromStream : Reading message");
String ret=in.readLine();
Log.i("AsynkTask", "readFromStream : read "+ret);
return ret;
} else {
Log.i("AsynkTask", "readFromStream : Cannot Read, Socket is closed");
}
} catch (Exception e) {
Log.i("AsynkTask", "readFromStream : Reading failed"+e.getClass());
}
return null;
}
}
this is my main activity
public class MainActivity extends Activity {
private EditText view_email;
private EditText view_password;
TextView result;
ConnectionHandler conhandler;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
conhandler = new ConnectionHandler();
conhandler.execute();
}
public void register(View view) {
view_email= (EditText) findViewById(R.id.email);
view_password = (EditText) findViewById(R.id.password);
String email=view_email.getText().toString();
String password=view_password.getText().toString();
conhandler.writeToStream("register");
conhandler.writeToStream(email);
conhandler.writeToStream(password);
String res=conhandler.readFromStream(); //here's the exception
result=(TextView) findViewById(R.id.result);
result.setText(res);
}
}
There are two Solution of this Problem.
1) Don't write network call in Main UIThread, Use Async Task for that.
2) Write below code into your MainActivity file after setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
And below import statement into your java file.
import android.os.StrictMode;
android.os.NetworkOnMainThreadException
this eror comes With HoneyComb(3.0 or Later).
you can not perform a networking operation on its main thread as documentation says. to getting ride of this you must use handler or asynctask. AFAIK There is no another way to do it.
you can See this for More Details WHY ICS Crashes your App
Try Using Below Code Snippet
new Thread(){
public void run(){
//do your Code Here
}
}.start();
Is it possible to scan several ports at once with AsyncTask? I am totally new to AsyncTask, so I have no clue what I am doing. Even after reading all tutorials on the internet about AsyncTask (eg Vogella etc.) I still can't understand how to make this happen.
Here is the code I have at the moment:
public class MainActivity extends Activity {
EditText et;
Button b;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et = (EditText) findViewById(R.id.editText1);
b = (Button) findViewById(R.id.button1);
}
public void start(View view){
GetPorts task = new GetPorts();
task.execute(20,53,80,114,140);
}
private class GetPorts extends AsyncTask<Integer, Void, Vector<Integer>> {
Vector<Integer> openPorts = new Vector<Integer>();
#Override
protected Vector<Integer> doInBackground(Integer... ports) {
for(Integer port: ports){
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", port), 500);
socket.close();
openPorts.add(port);
} catch (Exception ex) {
}
}
return openPorts;
}
}
}
the ports 20,53,80 etc are the example porst I'd like to check (there could be up to 65535 ports). I thought checking ports and adding them to Vector and then returning this Vector would be a good idea, but I have no idea how to do that. I wonder if my Vector "openPorts" is going to reset with every new port to scan, and will this AsyncTask be able to scan multiple ports at the same time?
I have created the working solution with Java SE and I'm gonna paste it here to clarify what I am after of.
Java SE code:
public class Scanner {
private final String ip;
private final int sPort, ePort, timeout, poolSize;
private Vector<Integer> openPorts = new Vector<Integer>();
private final ExecutorService es;
private Collection<Future<?>> futures = new LinkedList<Future<?>>();
public Scanner(String ip, int sPort, int ePort, int timeout, int poolSize) {
this.ip = ip;
this.sPort = sPort;
this.ePort = ePort;
this.timeout = timeout;
this.poolSize = poolSize;
es = Executors.newFixedThreadPool(this.poolSize);
}
public Vector<Integer> getPorts() {
Collections.sort(openPorts);
return openPorts;
}
public void runScanner() {
for (int startPort = sPort; startPort <= ePort; startPort++) {
futures.add(es.submit(new Check(ip, startPort, timeout)));
}
es.shutdown();
}
public void stopScanner(){
for (Future<?> future : futures) {
future.cancel(true);
}
}
private class Check implements Runnable {
private String ip;
private int port, timeout;
private Check(String ip, int port, int timeout) {
this.ip = ip;
this.port = port;
this.timeout = timeout;
}
public void run() {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(ip, port), timeout);
socket.close();
openPorts.add(port);
} catch (Exception ex) {
}
}
}
}
Your vector will be reset only when you instanciate a new GetPorts class (as usual).
Your code looks just fine. If your problem is to retrieve the result of the AsyncTask, you have two main ways to achieve it.
You can just call Vector<Integer> v = new GetPorts().execute(20,53,80,114,140).get(); but it's not often a proper way.
Or you can implements callback in the AsyncTask post execute callback.
#Override
protected void onPostExecute(Vector<Integer> result) {
}
Your AsyncTask should be like this:
private class GetPorts extends AsyncTask<Integer, Void, Vector<Integer>> {
public interface MyCallbackInterface {
public void myCallback(Vector<Integer> ports);
}
MyCallbackInterface listener;
Vector<Integer> openPorts = new Vector<Integer>();
public GetPorts(MyCallbackInterface listener) {
this.listener = listener;
}
#Override
protected Vector<Integer> doInBackground(Integer... ports) {
for(Integer port: ports){
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("localhost", port), 500);
socket.close();
openPorts.add(port);
} catch (Exception ex) {
}
}
return openPorts;
}
#Override
protected void onPostExecute(Vector<Integer> result) {
listener.myCallback(result);
}
}
Then in the task caller which implements MyCallbackInterface, you can do:
new GetPorts(this).execute(20,53,80,114,140);
And doing what you want in :
#Override
public void myCallback(Vector<Integer> ports) {
}