the android code
public class androidconn extends Activity {
private rabbitmqclient mConsumer;
private TextView mOutput;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conn);
//The output TextView we'll use to display messages
mOutput = (TextView) findViewById(R.id.moutput);
//Create the consumer
mConsumer = new rabbitmqclient("10.0.2.2:5672",
"logs",
"fanout");
//Connect to broker
mConsumer.connectToRabbitMQ();
//register for messages
mConsumer.setOnReceiveMessageHandler(new OnReceiveMessageHandler(){
public void onReceiveMessage(byte[] message) {
String text = "";
try {
text = new String(message, "UTF");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
mOutput.append("\n"+text);
}
});
}
#Override
protected void onResume() {
super.onPause();
mConsumer.connectToRabbitMQ();
}
#Override
protected void onPause() {
super.onPause();
mConsumer.dispose();
}
}
rabbitmq code
public abstract class rabbitmq {
public String mServer;
public String mExchange;
protected com.rabbitmq.client.Channel mModel = null;
protected Connection mConnection;
protected boolean Running ;
protected String MyExchangeType ;
/**
*
* #param server The server address
* #param exchange The named exchange
* #param exchangeType The exchange type name
* #return
*/
public rabbitmq(String server, String exchange, String exchangeType)
{
mServer = server;
mExchange = exchange;
MyExchangeType = exchangeType;
}
public void Dispose() throws SQLException
{
Running = false;
try {
if (mConnection!=null)
mConnection.close();
if (mModel != null)
mModel.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/** * Connect to the broker and create the exchange
* #return success
*/
public boolean connectToRabbitMQ()
{
if(mModel!= null && mModel.isOpen() )//already declared
return true;
try
{
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost(mServer);
connectionFactory.setPort(5672);
mConnection = (Connection) connectionFactory.newConnection();
mModel = ((com.rabbitmq.client.Connection) mConnection).createChannel();
mModel.exchangeDeclare(mExchange, MyExchangeType, true);
return true;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
}
rabbitmqclient code
public class rabbitmqclient extends rabbitmq{
public rabbitmqclient(
String server,String exchange,String exchangeType) {
super(server,exchange,exchangeType);
}
//The Queue name for this consumer
private String mQueue;
private QueueingConsumer MySubscription;
//last message to post back
private byte[] mLastMessage;
// An interface to be implemented by an object that is interested in messages(listener)
public interface OnReceiveMessageHandler{
public void onReceiveMessage(byte[] message);
};
//A reference to the listener, we can only have one at a time(for now)
private OnReceiveMessageHandler mOnReceiveMessageHandler;
/**
*
* Set the callback for received messages
* #param handler The callback
*/ public void setOnReceiveMessageHandler(OnReceiveMessageHandler handler)
{
mOnReceiveMessageHandler = handler;
};
private Handler mMessageHandler = new Handler();
private Handler mConsumeHandler = new Handler();
// Create runnable for posting back to main thread
final Runnable mReturnMessage = new Runnable() {
public void run() {
mOnReceiveMessageHandler.onReceiveMessage(mLastMessage);
}
};
final Runnable mConsumeRunner = new Runnable() {
public void run() {
Consume();
}
};
/**
* Create Exchange and then start consuming. A binding needs to be added before any messages will be delivered
*/
#Override
public boolean connectToRabbitMQ()
{
if(super.connectToRabbitMQ())
{
try {
mQueue = mModel.queueDeclare().getQueue();
MySubscription = new QueueingConsumer(mModel);
mModel.basicConsume(mQueue, false, MySubscription);
} catch (IOException e) {
e.printStackTrace();
return false;
}
if (MyExchangeType == "fanout")
AddBinding("");//fanout has default binding
Running = true;
mConsumeHandler.post(mConsumeRunner);
return true;
}
return false;
}
/**
* Add a binding between this consumers Queue and the Exchange with routingKey
* #param routingKey the binding key eg GOOG
*/
public void AddBinding(String routingKey)
{
try {
mModel.queueBind(mQueue, mExchange, routingKey);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* Remove binding between this consumers Queue and the Exchange with routingKey
* #param routingKey the binding key eg GOOG
*/
public void RemoveBinding(String routingKey)
{
try {
mModel.queueUnbind(mQueue, mExchange, routingKey);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void Consume()
{
Thread thread = new Thread()
{
#Override
public void run() {
while(Running){
QueueingConsumer.Delivery delivery;
try {
delivery = MySubscription.nextDelivery();
mLastMessage = delivery.getBody();
mMessageHandler.post(mReturnMessage);
try {
mModel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
} catch (IOException e) {
e.printStackTrace();
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
};
thread.start();
}
public void dispose(){
Running = false;
}
}
and the logcat is
07-24 22:57:45.412: D/SntpClient(59): request time failed: java.net.SocketException: Address family not supported by protocol
kindly tell me the eror
make sure the rabbitmq server is not blocking the connection and the connectivity information supplied is correct. You can add this to the android manifest file as well:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Catch SocketException and ensure that you can connect to the destination ip address/port number.
Related
I'm having a bit of trouble using the singleton pattern correctly in my android studio project. I created a textView in my mainActivity class in which I want to set the text of that textView the string value of the variable "a" in the GrouseSingleton class. However, the textView always displays as "hello" (the way it was initialized) and not the actual string it should be (it should be "mainly cloudy skies", parsed from the website). I'm assuming that I'm not set the variable "a" correctly in the singleton class. Any help would be appreciated, thanks!
SINGLETON CLASS CODE:
public class GrouseSingleton extends AppCompatActivity {
private static GrouseSingleton instance = null;
public Document grouseWeather;
public String a = "hello";
private GrouseSingleton() throws IOException {
startThread();
}
public static GrouseSingleton getInstance() throws IOException {
if (instance == null) {
instance = new GrouseSingleton();
}
return instance;
}
public void startThread() throws IOException {
new Thread() {
public void run() {
try {
grouseWeather = Jsoup.connect("https://www.grousemountain.com/current_conditions#weather").get();
runOnUiThread( new Runnable()
{
public void run()
{
a = grouseWeather.select("h3.metric").first().text();
setA(a);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
public void setA(String a) {
this.a = a;
}
}
MAIN ACITVITY CODE:
try {
grouseSingleton = GrouseSingleton.getInstance();
} catch (IOException e) {
e.printStackTrace();
}
TextView tv45 = findViewById(R.id.textView45);
tv45.setText(grouseSingleton.a);
Your singleton is fine. The issue is that you create the instance of class GrouseSingleton and then right after that you get the value of a which is the default value "hello" . So you need to use an interface like below to inform your activity when the value of a is fetched from server:
public interface ResultListener {
void onResultFetched(int textViewId, String txt);
}
In your Activity:
try {
grouseSingleton = GrouseSingleton.getInstance(new ResultListener () {
#Override
public void onResultFetched(int textViewId, String txt) {
TextView tv45 = findViewById(id);
tv45.setText(txt);
});
grouseSingleton.startThread();
} catch (IOException e) {
e.printStackTrace();
}
set the listener in your GrouseSingleton class:
private static ResultListener listener;
public static GrouseSingleton getInstance(ResultListener listener) throws IOException {
if (instance == null) {
instance = new GrouseSingleton();
GrouseSingleton.listener = listener;
}
return instance;
}
public void startThread() throws IOException {
new Thread() {
public void run() {
try {
grouseWeather = Jsoup.connect("https://www.grousemountain.com/current_conditions#weather").get();
runOnUiThread( new Runnable()
{
public void run()
{
a = grouseWeather.select("h3.metric").first().text();
listener.onResultFetched(txtViewId, a);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
All code is fine. But the problem is before load data textview set default value hello. Afterload data it's cannot update the value. To simply achieve this just sent your textView as a parameter when calling your singleton. like:
SingletonClass:
public class GrouseSingleton extends AppCompatActivity {
private static GrouseSingleton instance = null;
public Document grouseWeather;
public String a = "hello";
TextView textView;
private GrouseSingleton(TextView textView) throws IOException {
this.textView = textView;
startThread();
}
public static GrouseSingleton getInstance(TextView textView) throws IOException {
if (instance == null) {
instance = new GrouseSingleton(textView);
}
return instance;
}
public void startThread() throws IOException {
new Thread() {
public void run() {
try {
grouseWeather = Jsoup.connect("https://www.grousemountain.com/current_conditions#weather").get();
runOnUiThread( new Runnable()
{
public void run()
{
a = grouseWeather.select("h3.metric").first().text();
textView.setText(a);
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
And from MAinActivity:
TextView tv45 = findViewById(R.id.textView45);
try {
grouseSingleton = GrouseSingleton.getInstance(tv45);
} catch (IOException e) {
e.printStackTrace();
}
tv45.setText(grouseSingleton.a);
I'm using sample demo of
https://github.com/aosp-mirror/platform_development/tree/master/samples/SipDemo
the programing is ok, it doesn´t show issues, but when I configure this, it shows message Registration failed.
I´m programing with android studio, and the server is asterisk.
I tried with soiper and and it works.
public class WalkieTalkieActivity extends Activity implements View.OnTouchListener {
public String sipAddress = null;
public SipManager manager = null;
public SipProfile me = null;
public SipAudioCall call = null;
public IncomingCallReceiver callReceiver;
private static final int CALL_ADDRESS = 1;
private static final int SET_AUTH_INFO = 2;
private static final int UPDATE_SETTINGS_DIALOG = 3;
private static final int HANG_UP = 4;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_walkie_talkie);
ToggleButton pushToTalkButton = (ToggleButton) findViewById(R.id.pushToTalk);
pushToTalkButton.setOnTouchListener(this);
// Set up the intent filter. This will be used to fire an
// IncomingCallReceiver when someone calls the SIP address used by this
// application.
IntentFilter filter = new IntentFilter();
filter.addAction("android.SipDemo.INCOMING_CALL");
callReceiver = new IncomingCallReceiver();
this.registerReceiver(callReceiver, filter);
// "Push to talk" can be a serious pain when the screen keeps turning off.
// Let's prevent that.
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
initializeManager();
}
#Override
public void onStart() {
super.onStart();
// When we get back from the preference setting Activity, assume
// settings have changed, and re-login with new auth info.
initializeManager();
}
#Override
public void onDestroy() {
super.onDestroy();
if (call != null) {
call.close();
}
closeLocalProfile();
if (callReceiver != null) {
this.unregisterReceiver(callReceiver);
}
}
public void initializeManager() {
if(manager == null) {
manager = SipManager.newInstance(this);
}
initializeLocalProfile();
}
/**
* Logs you into your SIP provider, registering this device as the location to
* send SIP calls to for your SIP address.
*/
public void initializeLocalProfile() {
if (manager == null) {
return;
}
if (me != null) {
closeLocalProfile();
}
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
/* String username = prefs.getString("namePref", "");
String domain = prefs.getString("domainPref", "");
String password = prefs.getString("passPref", ""); */
String username = "12";
String domain = "192.168.1.37";
String password = "1234";
if (username.length() == 0 || domain.length() == 0 || password.length() == 0) {
showDialog(UPDATE_SETTINGS_DIALOG);
return;
}
try {
SipProfile.Builder builder = new SipProfile.Builder(username, domain);
builder.setAuthUserName("12");
builder.setDisplayName("12");
builder.setProfileName("12");
builder.setPassword(password);
me = builder.build();
Intent i = new Intent();
i.setAction("android.SipDemo.INCOMING_CALL");
PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, Intent.FILL_IN_DATA);
manager.open(me, pi, null);
// This listener must be added AFTER manager.open is called,
// Otherwise the methods aren't guaranteed to fire.
manager.setRegistrationListener(me.getUriString(), new SipRegistrationListener() {
public void onRegistering(String localProfileUri) {
updateStatus("Registering with SIP Server...");
}
public void onRegistrationDone(String localProfileUri, long expiryTime) {
updateStatus("Ready");
}
public void onRegistrationFailed(String localProfileUri, int errorCode,
String errorMessage) {
updateStatus("Registration failed. Please check settings.");
}
});
} catch (ParseException pe) {
updateStatus("Connection Error.");
} catch (SipException se) {
updateStatus("Connection error.");
}
}
/**
* Closes out your local profile, freeing associated objects into memory
* and unregistering your device from the server.
*/
public void closeLocalProfile() {
if (manager == null) {
return;
}
try {
if (me != null) {
manager.close(me.getUriString());
}
} catch (Exception ee) {
// Log.d("WalkieTalkieActivity/onDestroy", "Failed to close local profile.", ee);
}
}
/**
* Make an outgoing call.
*/
public void initiateCall() {
updateStatus(sipAddress);
try {
SipAudioCall.Listener listener = new SipAudioCall.Listener() {
// Much of the client's interaction with the SIP Stack will
// happen via listeners. Even making an outgoing call, don't
// forget to set up a listener to set things up once the call is established.
#Override
public void onCallEstablished(SipAudioCall call) {
call.startAudio();
call.setSpeakerMode(true);
call.toggleMute();
updateStatus(call);
}
#Override
public void onCallEnded(SipAudioCall call) {
updateStatus("Ready.");
}
};
call = manager.makeAudioCall(me.getUriString(), sipAddress, listener, 30);
}
catch (Exception e) {
// Log.i("WalkieTalkieActivity/InitiateCall", "Error when trying to close manager.", e);
if (me != null) {
try {
manager.close(me.getUriString());
} catch (Exception ee) {
// Log.i("WalkieTalkieActivity/InitiateCall",
// "Error when trying to close manager.", ee);
ee.printStackTrace();
}
}
if (call != null) {
call.close();
}
}
}
/**
* Updates the status box at the top of the UI with a messege of your choice.
* #param status The String to display in the status box.
*/
public void updateStatus(final String status) {
// Be a good citizen. Make sure UI changes fire on the UI thread.
this.runOnUiThread(new Runnable() {
public void run() {
TextView labelView = (TextView) findViewById(R.id.sipLabel);
labelView.setText(status);
}
});
}
/**
* Updates the status box with the SIP address of the current call.
* #param call The current, active call.
*/
public void updateStatus(SipAudioCall call) {
String useName = call.getPeerProfile().getDisplayName();
if(useName == null) {
useName = call.getPeerProfile().getUserName();
}
updateStatus(useName + "#" + call.getPeerProfile().getSipDomain());
}
/**
* Updates whether or not the user's voice is muted, depending on whether the button is pressed.
* #param v The View where the touch event is being fired.
* #param event The motion to act on.
* #return boolean Returns false to indicate that the parent view should handle the touch event
* as it normally would.
*/
public boolean onTouch(View v, MotionEvent event) {
if (call == null) {
return false;
} else if (event.getAction() == MotionEvent.ACTION_DOWN && call != null && call.isMuted()) {
call.toggleMute();
} else if (event.getAction() == MotionEvent.ACTION_UP && !call.isMuted()) {
call.toggleMute();
}
return false;
}
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, CALL_ADDRESS, 0, "Call someone");
menu.add(0, SET_AUTH_INFO, 0, "Edit your SIP Info.");
menu.add(0, HANG_UP, 0, "End Current Call.");
return true;
}
}
Think that should be user#domain ...and an IP address is not a domain.
I made a simple program on Android which connects to a server using Socket and receives some data. When I code in this way, it works well:
public class MainActivity extends Activity
{
EditText ip_box;
Button login_button;
TextView text;
Handler handler;
final int port = 12121;
Socket socket;
String ip;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();//omitted
handler = new Handler()
{
public void handleMessage(Message msg)
{
String words = (String)msg.obj;
text.setText((String)msg.obj);
}
};
class GetThread implements Runnable
{
public void getMsg()
{
try
{
Scanner in = new Scanner(socket.getInputStream());
String gotmsg = in.nextLine();
Message msg = new Message();
msg.obj = gotmsg;
MainActivity.this.handler.sendMessage(msg);
} catch (UnknownHostException e)
{
Message msg = new Message();
msg.obj = "net error";
MainActivity.this.handler.sendMessage(msg);
} catch (IOException e)
{
Message msg = new Message();
msg.obj = "net error";
MainActivity.this.handler.sendMessage(msg);
}
}
#Override
public void run()
{
try
{
socket = new Socket();
socket.connect(new InetSocketAddress(ip, port) , 5000);
} catch (UnknownHostException e)
{
...
} catch (IOException e) {
...
}
if( socket != null)
getMsg();
else
{
...
}
}
}
login_button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
ip = ip_box.getText().toString();
GetThread g = new GetThread();
new Thread(g).start();
}
});
}
}
And what I'm going to do is to make socket connections an independent class. I made the class in this way:
public class ClientSocketManager
{
String ip;
int port;
Socket socket;
Handler handler; //use this to send messages
/**
* Thread to get message from server
* #author Zero
*
*/
class GetThread implements Runnable
{
#Override
public void run()
{
try
{
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while(true)
{
String input = in.readLine();
if(input!=null)
{
Message msg = new Message();
msg.obj = input;
handler.sendMessage(msg);
}
}
}
catch (IOException e)
{
System.out.println("NetThreadIOException");
Message msg = new Message();
msg.obj = "net error";
handler.sendMessage(msg);
}
catch (NullPointerException e)
{
//System.out.println("NetThreadIOException");
Message msg = new Message();
msg.obj = "net error";
handler.sendMessage(msg);
}
}
}
/**
* Thread to login to server
* #author Zero
*
*/
class LoginThread implements Runnable
{
boolean ok;
#Override
public void run()
{
try
{
socket = new Socket();
socket.connect(new InetSocketAddress(ip, port) , 5000);
} catch (UnknownHostException e)
{
System.out.println("UnknownHostException");
Message msg = new Message();
msg.obj = "did not login";
handler.sendMessage(msg);
ok=false;
} catch (IOException e) {
System.out.println("IOException");
Message msg = new Message();
msg.obj = "did not login";
handler.sendMessage(msg);
ok=false;
}
}
}
public ClientSocketManager(){}
/**
* Create a new ClientSocketManager
* #param _ip
* #param _port
* #param _handler
*/
public ClientSocketManager(String _ip, int _port, Handler _handler)
{
ip = _ip;
port = _port;
handler = _handler;
}
public boolean login()
{
LoginThread login_thread = new LoginThread();
new Thread(login_thread).start();
return login_thread.ok;
}
public void openGetThread()
{
GetThread getThread = new GetThread();
new Thread(getThread).start();
}
}
And in the main Activity, I use the ClientSocketManager like this:
login_button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
ip = ip_box.getText().toString();
client_socket_manager = new ClientSocketManager(ip, port, handler);
boolean logged = client_socket_manager.login();
//if(!logged)
// return;
client_socket_manager.openGetThread();
}
})
Now it throws IOException on String input = in.readLine();. I'm curious about it. What's the possible reason?
Thank you very much!
The reason maybe:
client_socket_manager.login() and client_socket_manager.openGetThread() started two threads run concurrently to do two actions login and get. So when you have not logged in yet, the action get was performed.
I think the problem is that there is no guarantee in your code that the GetThread will execute after the LoginThread. I see that you have commented the code checking for a logged in status. You need to put that back in.
boolean loggedIn = false;
class LoginThread implements Runnable
{
boolean ok;
#Override
public void run()
{
try
{
socket = new Socket();
socket.connect(new InetSocketAddress(ip, port) , 5000);
loggedIn = true;
} catch (UnknownHostException e)
{
System.out.println("UnknownHostException");
Message msg = new Message();
msg.obj = "did not login";
handler.sendMessage(msg);
ok=false;
} catch (IOException e) {
System.out.println("IOException");
Message msg = new Message();
msg.obj = "did not login";
handler.sendMessage(msg);
ok=false;
}
}
}
and later check for this loggeddIn flag before running the GetThread
client_socket_manager = new ClientSocketManager(ip, port, handler);
client_socket_manager.login();
while (true){
if(loggedIn){
client_socket_manager.openGetThread();
break;
}
Thread.sleep(1000); //wait 1 sec before retrying
}
I have an activity that creates an AsyncTask to test an ftp connection via an FTPHelper class. The Activity shows a Toast with the boolean status of the connection, either success or fail. How can I show the exact replycode or replystring in the Activity?
Activity:
TestConnection task = new TestConnection(NewSite.this,
_address, _user, _pass, p, new testConnInterface() {
#Override
public void testConnection(boolean result) {
if (result == true) {
Toast.makeText(NewSite.this,
"Connection Succesful",
Toast.LENGTH_LONG).show();
} else {
Toast.makeText(NewSite.this,
"Connection Failed:" + result,
Toast.LENGTH_LONG).show();
}
}
});
task.execute();
TestConection.java
public class TestConnection extends AsyncTask<Void, Void, Boolean> {
private Context mContext;
private testConnInterface mListener;
private FTPHelper ftpHelper = new FTPHelper();
private String _address;
private String _user;
private String _pass;
private int _port;
ProgressDialog progressDialog;
public interface testConnInterface {
public void testConnection(boolean result);
}
public TestConnection(Context context, String address, String user,
String pass, int port, testConnInterface mListener) {
mContext = context;
_address = address;
_user = user;
_pass = pass;
_port = port;
this.mListener = mListener;
}
// declare other objects as per your need
#Override
protected void onPreExecute() {
progressDialog = ProgressDialog.show(mContext, "Please wait",
"Attempting to connect", true);
// do initialization of required objects objects here
};
#Override
protected Boolean doInBackground(Void... params) {
boolean status = ftpHelper.ftpConnect(_address, _user, _pass, _port);
return status;
}
#Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
if (mListener != null)
mListener.testConnection(result);
progressDialog.dismiss();
};
}
FTPHelper.java
public class FTPHelper {
public static FTPClient mFTPClient = null;
public FTPHelper() {
// TODO Auto-generated constructor stub
}
public boolean ftpConnect(String host, String username, String password,
int port) {
try {
mFTPClient = new FTPClient();
// connecting to the host
mFTPClient.connect(host, port);
// now check the reply code, if positive mean connection success
if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
// login using username & password
boolean status = mFTPClient.login(username, password);
/*
* Set File Transfer Mode
*
* To avoid corruption issue you must specified a correct
* transfer mode, such as ASCII_FILE_TYPE, BINARY_FILE_TYPE,
* EBCDIC_FILE_TYPE .etc. Here, I use BINARY_FILE_TYPE for
* transferring text, image, and compressed files.
*/
mFTPClient.setFileType(FTP.BINARY_FILE_TYPE);
mFTPClient.enterLocalPassiveMode();
showServerReply(mFTPClient);
return status;
}
} catch (Exception e) {
// Log.d(TAG, "Error: could not connect to host " + host );
}
return false;
}
public boolean ftpDisconnect() {
try {
mFTPClient.logout();
mFTPClient.disconnect();
return true;
} catch (Exception e) {
// Log.d(TAG,
// "Error occurred while disconnecting from ftp server.");
}
return false;
}
public String ftpGetCurrentWorkingDirectory() {
try {
String workingDir = mFTPClient.printWorkingDirectory();
return workingDir;
} catch (Exception e) {
Log.i("Error working dir", e.toString());
}
return null;
}
Basically I want to know how to return the getReplyCode() to my Activity.
I have an android application that is a client for a simple chat server. I am able to connect to the server and my ObjectStreams. The problem is when I receive a message, the thread that handles my server connection calls upon my display message which updates the list view.
I am getting the error "only the original thread that created a view hierarchy can touch its views."
I am pretty sure its because I'm calling my displayMessage() method from my connect thread, but I am not sure how to organize my threads to have a connection to the server and dynamically update my listview.
Here is my main activity.
public class MainActivity extends Activity {
private Connection serverConnection;
private ArrayList<String> listItems = new ArrayList<String>();
private ArrayAdapter<String> adapter;
/**
* Sets the ArrayAdaptor, and starts the connectThread.
*/
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
runOnUiThread(new Runnable() {
public void run() {
ListView listview = (ListView) findViewById(R.id.list);
adapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,
listItems);
listview.setAdapter(adapter);
}
});
/**
* Starts a new connection Thread
*/
Thread connectThread = new Thread(new Runnable(){
public void run(){
serverConnection = new Connection(MainActivity.this);
serverConnection.run();
}
});
connectThread.start();
}
/**
* Adds a message to the list view.
* #param string - message to be added.
*/
public void displayMessage(String string) {
listItems.add(string);
adapter.notifyDataSetChanged();
}
}
Here is my connection thread class.
public class Connection extends Thread {
private Socket client;
private ObjectOutputStream output;
private ObjectInputStream input;
private MainActivity mainActivity;
private String message;
/**
* Constructor starts the socket and ObjectStreams
*
* #param mainActivity - reference to the MainActivity
*/
public Connection(MainActivity mainActivity) {
this.mainActivity = mainActivity;
try {
client = new Socket("192.168.1.105", 50499);
mainActivity.displayMessage("Connected to: "
+ client.getInetAddress().getHostName());
output = new ObjectOutputStream(client.getOutputStream());
output.flush();
input = new ObjectInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Run method for the Thread.
*/
public void run() {
for (;;) {
try {
message = (String) input.readObject();
mainActivity.displayMessage(message);
} catch (OptionalDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
You are updating Ui on the background thread. You should update ui on the ui thread. Move your code that updates ui in the background thread. You are refreshing your listview on the background thread.
mainActivity.displayMessage("Connected to: "
+ client.getInetAddress().getHostName());
mainActivity.displayMessage(message);
public void displayMessage(String string) {
listItems.add(string);
adapter.notifyDataSetChanged();
}
The above should be outside the thread or You can use runonuithread inside the thread to update ui.
runOnUiThread(new Runnable() {
#Override
public void run() {
// update ui
}
});
Another way would be to use asynctask. Do all your network related operation in doInbackground() and update ui in onPostExecute().
Async Task
Edit: Not sure what you are trying to do.
public class MainActivity extends Activity {
private Connection serverConnection;
private ArrayList<String> listItems = new ArrayList<String>();
private ArrayAdapter<String> adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listview = (ListView) findViewById(R.id.lv);
adapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,
listItems);
listview.setAdapter(adapter);
// use a button and on button click start the thread.
Thread connectThread = new Thread(new Runnable(){
public void run(){
serverConnection = new Connection(MainActivity.this);
serverConnection.run();
}
});
connectThread.start();
}
public void displayMessage(String string) {
listItems.add(string);
adapter.notifyDataSetChanged();
}
class Connection extends Thread {
private Socket client;
private ObjectOutputStream output;
private ObjectInputStream input;
private MainActivity mainActivity;
private String message;
public Connection(MainActivity mainActivity) {
this.mainActivity = mainActivity;
try {
client = new Socket("192.168.1.105", 50499);
runOnUiThread(new Runnable() {
#Override
public void run() {
displayMessage("Connected to: "
);
}
});
output = new ObjectOutputStream(client.getOutputStream());
output.flush();
input = new ObjectInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void run() {
for (;;) {
try {
message = (String) input.readObject();
runOnUiThread(new Runnable() {
#Override
public void run() {
displayMessage(message);
}
});
} catch (OptionalDataException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}