I want create Socket connection but i have some problem. I must create it in new Thread but i can not.
public class SocketManager {
private static SocketManager instance;
private BufferedReader in;
private PrintWriter out;
private Socket mSocket = null;
public static SocketManager me() {
if (instance == null) {
instance = new SocketManager();
}
return instance;
}
public void connection() {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
mSocket = new Socket(Constants.CHAT_SERVER_URL, 4444);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}.execute();
}
public boolean isConnected() {
return mSocket.isConnected();
}
and
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
status = (TextView) findViewById(R.id.status);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
SocketManager.me().connection();
if (SocketManager.me().isConnected()) {
status.setText("Connected");
} else {
status.setText("Disconnected");
}
I have error:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.net.Socket.isConnected()' on a null object reference
Becouse mSocket create in new Thread and when i call it it == null; How can create mSocket in new Thread and use it?
Best way is to use an interface.
Create an interface in your Socketmanager class
public class SocketManager {
private static SocketManager instance;
private SocketListner listner;
public interface SocketListner {
void onConnectionSuccess();
void onConnectionFailed();
}
public void connection(SocketListner listner) {
this.listner = listner;
new ConnectionTask().execute();
}
And return a boolean value from doInBackGround() method to check if the connection is success or not
class ConnectionTask new AsyncTask<Void, Void, Boolean>() {
#Override
protected Void doInBackground(Void... params) {
//...your code
}
#Override
protected void onPostExecute(Boolean result) {
if(result) {
listner.onConnectionSuccess();
} else {
listner.onConnectionFailed();
}
}
}
And in your activity implement the interface
public class YourActivity imlpements SocketListner {
#Override
protected void onCreate(Bundle savedInstanceState) {
//your code
..
}
#Override
void onConnectionSuccess() {
//your socket is connected
status.setText("Connected");
}
#Override
void onConnectionFailed() {
status.setText("Disconnected");
}
}
I think method "isConnected()" is trying to access mSocket before it is initialized.
Try to change it to:
public boolean isConnected() {
return mSocket == null ? false : mSocket.isConnected();
}
This will avoid the NullPointerException on this method.
But the correct approach here would be to use a callback so the child thread can inform the main thread when it has finished.
public class SocketTask extends AsyncTask<Void, Void, Void> {
public interface AsyncTaskListener<T> {
void onTaskCompleted(T t);
}
private final AsyncTaskListener<String> listener;
public SocketTask(AsyncTaskListener<String> listener) {
this.listener = listener;
}
#Override
protected Void doInBackground(Void... params) {
try {
mSocket = new Socket(Constants.CHAT_SERVER_URL, 4444);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute() {
listener.onTaskCompleted();
}
}
You class SocketManager need to implement the callback:
public class SocketManager implements SocketTask.AsyncTaskListener {
}
Add boolean to know your asynctask is complete or not.
boolean mIsSocketInstanceCreated = false;
public void connection() {
new AsyncTask<Void, Void, Void>() {
#Override
protected Void doInBackground(Void... params) {
try {
mSocket = new Socket(Constants.CHAT_SERVER_URL, 4444);
mIsSocketInstanceCreated = true;
} catch (IOException e) {
e.printStackTrace();
mIsSocketInstanceCreated = false;
}
return null;
}
}.execute();
}
public boolean isConnected() {
if (mIsSocketInstanceCreated)
return mSocket.isConnected();
return false;
}
Related
This is the code i am working on. Here I cant update the UI until myOnResponse is finished.Because we are doing a doInBackgrnd, so my textresponse is empty. And Since onPostExecute is happening right after.
For his I think PublicProgres should help.
How to Call PublishProgress at AsyncTask ?
private class ConversationTask extends AsyncTask<String, Void, String> {
String textResponse = new String();
#Override
protected String doInBackground(String... params) {
System.out.println("in doInBackground");
MessageRequest newMessage = new MessageRequest.Builder().inputText(params[0]).context(context).build();
// async
GLS_service.message("xxxxxxxxx", newMessage).enqueue(new ServiceCallback<MessageResponse>() {
#Override
public void onResponse(MessageResponse response) {
context = response.getContext();
textResponse = response.getText().get(0);
action5(textResponse);
System.out.println(textResponse);
}
#Override
public void onFailure(Exception e) {
}
});
return textResponse;
}#Override protected void onPostExecute(String result) {
reply.setText(textResponse);
}
}
Please help.
I don't think that you have to use AsyncTask.
You can do something like this :
YourTask.java
public class YourTask implements Runnable {
private Handler handler;
private TextView textView;
public YourTask(TextView textView){
this.textView = textView;
handler = new Handler();
}
#Override
public void run() {
MessageRequest newMessage = new MessageRequest.Builder().inputText(params[0]).context(context).build();
GLS_service.message("xxxxxxxxx", newMessage).enqueue(new ServiceCallback<MessageResponse>() {
#Override
public void onResponse(MessageResponse response) {
final String textResponse = response.getText().get(0);
handler.post(new Runnable() {
#Override
public void run() {
if(textView != null){
textView.setText(textResponse);
}
}
});
}
#Override
public void onFailure(Exception e) {
}
});
}
}
And now how to use it :
SomeActivity.java
...
textView = (TextView) findViewById(R.id.textView);
...
Thread thread = new Thread(new YourTask(textView));
thread.start();
...
Nevertheless if you want to do this action in Asynktask just try this
private class ConversationTask extends AsyncTask<String, Void, Void> {
private Handler handler;
public ConversationTask(){
handler = new Handler();
}
#Override
protected Void doInBackground(String... params) {
MessageRequest newMessage = new MessageRequest.Builder().inputText(params[0]).context(context).build();
GLS_service.message("xxxxxxxxx", newMessage).enqueue(new ServiceCallback<MessageResponse>() {
#Override
public void onResponse(MessageResponse response) {
final String textResponse = response.getText().get(0);
handler.post(new Runnable() {
#Override
public void run() {
if(reply != null){
reply.setText(textResponse);
}
}
});
}
#Override
public void onFailure(Exception e) {
}
});
return null;
}
}
Hope it helps
I am trying to receive and send messages using Smack API but not been able to do it in a separate class due to some threads issue may be. But when now i ported all the code in MainActivity i wont be able to make a connection with server.Below is my MainActivity.class.
public class chatActivity extends AppCompatActivity {
private static final String DOMAIN = "192.168.0.109";
private static final String HOST = "192.168.0.109";
private static final int PORT = 5222;
private String userName ="";
private String passWord = "";
AbstractXMPPConnection connection ;
ChatManager chatmanager ;
Chat newChat;
ChatManager chatManager;
XMPPConnectionListener connectionListener = new XMPPConnectionListener();
private boolean connected;
private boolean isToasted;
private boolean chat_created;
private boolean loggedin;
Context context;
private MultiUserChat multiUserChat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
init("user123","user123");
}
});
t.start();
}
public void init(String userId,String pwd ) {
Log.i("XMPP", "Initializing!");
this.userName = userId;
this.passWord = pwd;
this.context = context;
XMPPTCPConnectionConfiguration.Builder configBuilder = XMPPTCPConnectionConfiguration.builder();
configBuilder.setUsernameAndPassword(userName, passWord);
configBuilder.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
configBuilder.setResource("Android");
configBuilder.setServiceName(DOMAIN);
configBuilder.setHost(HOST);
configBuilder.setPort(PORT);
//configBuilder.setDebuggerEnabled(true);
connection = new XMPPTCPConnection(configBuilder.build());
connection.addConnectionListener(connectionListener);
}
public class XMPPConnectionListener implements ConnectionListener {
#Override
public void connected(final XMPPConnection connection) {
Log.d("xmpp", "Connected!");
connected = true;
if (!connection.isAuthenticated()) {
System.out.println("Hellooooooooo11111");
login();
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// // TODO Auto-generated method stub
//new MainActivity().updateText(context);
}
});
}
}
#Override
public void connectionClosed() {
if (isToasted)
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
Log.d("xmpp", "ConnectionCLosed!");
connected = false;
chat_created = false;
loggedin = false;
}
#Override
public void connectionClosedOnError(Exception arg0) {
if (isToasted)
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
}
});
Log.d("xmpp", "ConnectionClosedOn Error!");
connected = false;
chat_created = false;
loggedin = false;
}
#Override
public void reconnectingIn(int arg0) {
Log.d("xmpp", "Reconnectingin " + arg0);
loggedin = false;
}
#Override
public void reconnectionFailed(Exception arg0) {
if (isToasted)
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
}
});
Log.d("xmpp", "ReconnectionFailed!");
connected = false;
chat_created = false;
loggedin = false;
}
#Override
public void reconnectionSuccessful() {
if (isToasted)
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
Log.d("xmpp", "ReconnectionSuccessful");
connected = true;
chat_created = false;
loggedin = false;
}
#Override
public void authenticated(XMPPConnection arg0, boolean arg1) {
Log.d("xmpp", "Authenticated!");
loggedin = true;
// joinChatRoom();
// sendMsg();
chat_created = false;
//sendMessage("body","jid");
//sendMsg();
new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(500);
// sendMsg();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
if (isToasted)
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
}
});
}
}
public void login() {
try {
connection.login(userName, passWord);
// sendMsg();
//Log.i("LOGIN", "Yey! We're connected to the Xmpp server!");
} catch (XMPPException | SmackException | IOException e) {
e.printStackTrace();
} catch (Exception e) {
}
}
}
My Question is how can I use smack API, I am not getting it at all that how to handle this network operations in main class.
I did try to run it in Asynch too.
Okay I found the solution i forgot to add the following method in my main class.
public void connectConnection()
{
AsyncTask<Void, Void, Boolean> connectionThread = new AsyncTask<Void, Void, Boolean>() {
#Override
protected Boolean doInBackground(Void... arg0) {
// Create a connection
try {
connection.connect();
login();
connected = true;
} catch (IOException e) {
} catch (SmackException e) {
} catch (XMPPException e) {
}
return null;
}
};
connectionThread.execute();
}
This question already has answers here:
how to return result from asyn call
(2 answers)
Closed 7 years ago.
Activity.java
//Activity stuff
MyClass mc = new MyClass();
mc.getText();
public void dosomething() {
textview.setText(mc.getText());
}
MyClass.java
class MyClass {
String text;
public void setText() {
class GetTextFromWEB extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String url = urls[0];
String output;
//Getting text from web
return output;
}
#Override
protected void onPostExecute(String _text) {
text = _text;
}
}
String url = "google.com";
//Doing with url something
new GetText().execute(url);
}
public String getText() {return text;}
}
Promblem is - in activity setText do faster, then AsyncTask do it's job.
So when setText run, it's run like setText(null)
I need to check in activity, is asynk ended, so i have my text to set.
I hope i explained it
And i don't even need exactly AsyncTask, i need jsoup working, so if there is solution with another thread-class, with which jsoup will work, i can use it
Edit
class GetLyrics extends AsyncTask<String, Void, String> { //Class for getting lyrics
private Context con;
public GetLyrics(Context con) {
this.con = con;
}
#Override
protected String doInBackground(String... urls) {
//do something
}
#Override
protected void onPostExecute(String _lyrics) {
lyrics = _lyrics;
con.runOnUiThread(new Runnable() {
#Override
public void run() {
((TextView) findViewById(R.id.lyricsOutput)).setText(lyrics);
}
});
}
}
Call the method setting your text in the postExecute inside your AsyncTask or set the text directly on your postExecute method.
And wrap the line with setText() inside runOnUIThread (otherwise you will get an exception saying that the view can be accessed only by the thread that created it, since you are setting the text from async task).
Setting the text would be something like this
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
((TextView) findViewById(R.id.txtFieldName)).setText("your text");
}
});
That way you can quit worrying about checking if the async task is finished. But avoid doing complex ui operations like this. Since this is just setting the text on TextView, it should be allright.
1: Make my first project from my previous post and add some new lines in it to get data from http: api's.
public class Example extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_example);
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("parameter1", "xyz"));
params.add(new BasicNameValuePair("parameter2", "abc"));
params.add(new BasicNameValuePair("parameter3", "opqr"));
ServerConnection task = new ServerConnection(this, new ResultListener() {
#Override
public void result(String response) {
Toast.make(this, response, Toast.LENGTH_LONG).show();
}
#Override
public void loader(boolean visble) {
}
#Override
public void connectionLost(String error) {
Toast.make(this, error, Toast.LENGTH_LONG).show();
}
});
}
public class ServerConnection extends AsyncTask<String, String, String> implements Constant {
ResultListener listener;
private String Method = "GET";
private List<NameValuePair> params = new ArrayList<NameValuePair>();
private Context context;
private ConnectionDetector cd;
// public static Drawable drawable;
public ServerConnection(Context context, ResultListener r) {
this.context = context;
this.listener = r;
cd = new ConnectionDetector(context);
this.execute();
}
public boolean isConnection() {
return cd.isConnectingToInternet();
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected String doInBackground(String... arg0) {
if (!isConnection()) {
cancel(true);
return "Sorry!connection lost,try again or later";
}
ApiResponse air = new ApiResponse();
System.out.println("working hre" + "hi");
String json;
try {
json = air.makeHttpRequest(URL, getMethod(), getParams());
} catch (Exception e) {
json = e.getMessage();
cancel(true);
return json;
}
return json;
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
protected void onCancelled(String result) {
listener.connectionLost(result);
rl.connectionLost("Sorry!connection lost,try again or later");
super.onCancelled(result);
}
#Override
protected void onPostExecute(String result) {
System.out.println("onpost" + result);
listener.result(result);
listener.loader(true);
super.onPostExecute(result);
}
public String getMethod() {
return Method;
}
public void setMethod(String method) {
Method = method;
}
public List<NameValuePair> getParams() {
return params;
}
public void setParams(List<NameValuePair> params) {
this.params = params;
}
}
Example
I've created a component which downloads an Image (in the Android side) and I want to send back size details about that image (to the JS side) of my app.
Now, I can safely say that I can call my component from JS and it will respond back with data but as soon as I add in the Async element to download the image from an URL, read it and respond I get a NullpointerException as soon as I call my callback.invoke("response text");
My problematic code is:
public void loadImage(final String url, final Callback onLoadCallback) {
...
new AsyncTask<String, Void, Void>() {
#Override
protected Void doInBackground(String... url) {
try {
theImage = Glide.with(getReactApplicationContext()).load(url[0]).asBitmap().into(-1, -1).get();
}
catch ...
return null;
}
#Override
protected void onPostExecute(Void dummy) {
if (null != theImage) {
onLoadCallback.invoke("Success"); //<== THIS LINE HERE
}
}
}.execute(url);
...
}
Now, I get that it's because I'm trying to return on a sep thread back to the main thread via the callback but I'm not sure how in the heck I'm supposed to get the info I want back to the JS side?! This is my first attempt at a component in RN so be kind! :)
Extra Info - My React module:
var MY_Image = require('NativeModules').MYImage;
var myimage = {
loadImage(url, onLoad) {
MY_Image.loadImage(url, onLoad)
},
};
module.exports = myimage;
Then in my React app view:
...
componentDidMount: function() {
myImage.loadImage('[URL to Image]',onLoad=> {
console.log('Success: '+onLoad);
});
}
Thanks for the input everyone. I've managed to sort this. I needed a class-wide variable to hold the callback in and a callback handler. Here's my code:
public class MyClass extends ReactContextBaseJavaModule {
private Bitmap mTheImage;
private Callback mCallback;
private WritableMap mResults;
public MyClass(ReactApplicationContext reactContext) {
super(reactContext);
this.mContext = reactContext;
}
private void consumeCallback(String type, WritableMap obj) {
if(mCallback!=null) {
obj.putString("type", type);
mCallback.invoke(obj);
mCallback = null;
}
}
#ReactMethod
public void doMyStuff(final String input, final Callback callback) {
if(mCallback==null) {
mResults = Arguments.createMap();
}
mCallback = callback;
new AsyncTask<String, Void, Void>() {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(String... params) {
try {
String myValue = params[0];
mResults.putString("myValue", myValue);
mTheImage = [method to get the image]
}
catch(Exception e) {
}
return null;
}
protected void onPostExecute(Void dummy) {
if(null!=mTheImage && null!=mCallback) {
mResults.putInt("width", mImage.getWidth());
mResults.putInt("height",mImage.getHeight());
consumeCallback("success", mResults);
}
else {
consumeCallback("error", mResults);
}
}
}.execute(url);
}
}
I have AsyncTask class and I call it in my main class. I need to override the onPostExecute function and call inside ftpDisconnect(). But it does not work properly.
TempClass dj = new TempClass(serialnum) {
#Override
protected void onProgressUpdate(Integer... values) {
pr_bar.setProgress(values[0]);
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
//dj.ftpDisconnect(); //need to make this happen
super.onPostExecute(result);
}
};
dj.execute();
My TempClass:
public class TempClass extends AsyncTask<String, Integer, String> {
public TempClass(String serialnum) {
this.serialnum = serialnum;
}
#Override
protected String doInBackground(String... params) {
//do stuff
return null;
}
public boolean ftpDisconnect() {
try {
mFTPClient.disconnect();
return true;
} catch (Exception e) {
}
return false;
}
}
You can't access that instance of dj without making it final. You should be able to call ftpDisconnect from inside the class:
#Override
protected void onPostExecute(String result) {
ftpDisconnect();
super.onPostExecute(result);
}