I have some trouble with my Android app when it connect with other application, I use TCP protocol to communication between them. In my Android app, I try to receive message from other application and then I use Line Chart to visualize that data. At the first time, I connect my Android app with that application, It still receive message and still visualize in Line chart but when I turn off WIFI and turn it on and try to reconnect it but my Android app do not receive anymore.
This is my receive code :
private static class ReceiveMessage extends AsyncTask<Void, Void, Void> {
private String mess;
private IMessageListener listener;
private static ReceiveMessage _instance;
public static ReceiveMessage getInstance() {
if (_instance==null) {
_instance = new ReceiveMessage();
_instance.execute();
}
return _instance;
}
public void subscribe(IMessageListener listener) {
this.listener = listener;
}
#Override
protected Void doInBackground(Void... voids) {
do {
try {
inputStreamReader = new InputStreamReader(socket.getInputStream());
bufferedReader = new BufferedReader(inputStreamReader);
mess = bufferedReader.readLine();
listener.messageReceived(mess);
} catch(IOException e){
e.printStackTrace();
}
}while(socket.isConnected());
return null;
}
}
Thank for your help.
Related
I'm making an android app that uses a development server to respond api calls.
I set it up using the following guide:
https://github.com/GoogleCloudPlatform/gradle-appengine-templates/tree/master/HelloEndpoints
I used the skeleton code provided by google on the example, so my api and the AsyncTask that peforms the calls look like this:
MyEndpoint class:
/** An endpoint class we are exposing */
#Api(
name = "myApi",
version = "v1",
namespace = #ApiNamespace(
ownerDomain = "backend.myapplication.madelenko.example.com",
ownerName = "backend.myapplication.madelenko.example.com",
packagePath=""
)
)
public class MyEndpoint {
/** A simple endpoint method that takes a name and says Hi back */
#ApiMethod(name = "supplyJoke")
public MyBean supplyJoke() {
MyBean response = new MyBean();
response.setData(JokeDispenser.getJoke());
return response;
}
}
MyBean Class:
/** The object model for the data we are sending through endpoints */
public class MyBean {
private String myData;
public String getData() {
return myData;
}
public void setData(String data) {
myData = data;
}
}
The asyncTask:
public class FetchJokeTask extends AsyncTask<Pair<Context,String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.supplyJoke().execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
For some reason, when I click a button and launch an AsyncTask, I get a 404 error. The toast returns html with the contents of a 404 page.
I used the debugger to find out why and I know that the asyncTask tries to execute this line and fails:
return myApiService.supplyJoke().execute().getData();
Therefore, it returns an error message.
Is there anything wrong with my config?
Please help me to figure it out. Thanks.
P.S.: The problem is that the execute() method throws an IOException. I hope this extra piece gives you some context. Thank you very much.
I'm basically trying to start a Socket.IO connection in one activity (The LogIn Activity) and carry that throughout the various other activities. If anyone has any idea on what would work the best in this situation that would be great. All I need is probably a service that I can run in the background but I haven't been able to figure out how that works.
I tried doing this but that doesn't work.
public class KlassAttack extends Application {
Socket gameConnection;
#Override
public void onCreate() {
try {gameConnection = IO.socket("http://71.13.36.124:56543");}catch(URISyntaxException e){}
gameConnection.connect();
Log.e("TEST", "EEE");
}
}
U can make a singleton class
public class SocketIOClient {
private static Socket mSocket;
private static void initSocket(Activity activity) {
try {
mSocket = IO.socket(Constants.CHAT_SOCKET_URL);
} catch (URISyntaxException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public static Socket getInstance(Activity activity) {
if (mSocket != null) {
return mSocket;
} else {
initSocket(activity);
return mSocket;
}
} }
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.
public class SocketThread {
private boolean connect = false;
private String ip = "*********";
private int port = ****;
private Socket socket;
private SocketAsync socketAsync;
public SocketThread() {
socketAsync = new SocketAsync();
socketAsync.execute();
}
public void setMessenger(SocketServiceMessenger messenger) {
this.socketServiceMessenger = messenger;
}
public void setConnectFlag(boolean connect) {
this.connect = connect;
}
public void sentData(JSONObject json) {
socketAsync.sentData2(json);
}
private class SocketAsync extends AsyncTask<Void, Void, String> {
private PrintWriter printWriter;
#Override
protected String doInBackground(Void... params) {
String msgStr;
String type;
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"));
while(socket.isConnected()) {
msgStr = streamIn.readLine();
System.out.println(msgStr);
if(!connect) {
socket.close();
}
}
System.out.println("SocketDisconnected");
} catch (Exception e) {
System.out.println(e.toString());
}
return null;
}
public void sentData2(JSONObject json) {
if(socket.isConnected()) {
printWriter.println(json.toString());
printWriter.flush();
System.out.println("OUT : " + json);
}
}
}
I get android.os.NetworkOnMainThreadException when call sentData()
Now I use
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
to resolve the problem, but I want to know how to use asynctask in true way.
This code is for online game that receive message from server in realtime and it can also sent message to server from some activity by calling sentData().
Resolve
Example: Android bi-directional network socket using AsyncTask
You should set the class to be public and no outer class needed.
public class SocketAsync extends AsyncTask<String, String, String> {
private PrintWriter printWriter;
#Override
protected String doInBackground(String... params) {
//You do things here.
}
}
This is how you set up the class and in the Activity class, you simply call this by code like :
new SocketAsync(this).execute(/*Put parameters here.*/);
Hope this will help.
The method SocketAsync.sentData2() calls socket.isConnected(). This is being called on the main thread because something calls SocketThread.sendData2() on the main thread.
Code executes on the thread it is called from. Just because you put that code in your AsyncTask class does not mean it will be on a background thread. Only the code in doInBackground() is guaranteed to be executed in the background, because the Android framework takes care to call that method from a background thread. If you called it yourself, it would execute on whatever thread called it. sentData2() is no different.
You are using Asynctask wrong. When you call the execute method the doInBackground is called which runs on a different thread. You use the onPostExecute method from AsyncTask to get your data back to the main thread (a kind of callback method). This method runs on the main ui thread.
The sendData method would require a new AsyncTask, with a new doInbackground and a new call to execute.
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) {
}