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();
}
}
}
}
}
Related
I recently created an activity in my app. Now I wanted the user to download a .pdf file when he/she wants to view the guidelines. I wanted to implement this on a button. Any idea how to do this properly?
Heres my code below:
public class Exhibitor_Registration_Activity extends AppCompatActivity {
Button buttonDownload;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exhibitor_registration_);
this.setTitle("Buyer Registration");
Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
setSupportActionBar(myToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
myToolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp);
final Button buttonDownload = (Button) findViewById(R.id.buttonDownload);
buttonDownload.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view) {
try {
//this is the file you want to download from the remote server
String path ="http://www.manilafame.com/website-assets/downloads/exhibitor-application-kit/local/201704/1-Summary-of-Participation-Details-April-2017_MN_002.pdfp";
//this is the name of the local file you will create
String targetFileName = null;
boolean eof = false;
URL u = new URL(path);
HttpURLConnection c = (HttpURLConnection) u.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
FileOutputStream f = new FileOutputStream(new File("c:\\junk\\"+targetFileName));
InputStream in = c.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) {
f.write(buffer,0, len1);
}
f.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
I also got the source code from here and here.
if you want resumable, speed of download ...
follow this steps
create a class DownloadManager.java
public class DownloadManager extends AsyncTask<String,String,String>{
String downloadlink,fileDestination;
public static final int ON_INIT=100,ON_ERROR=102,ON_PROGRASS=103,ON_COMPLETED=104,STATUS_DOWNLOADED=1500,STATUS_NOT_YET=1501;
private onUpdateListener onUpdateListener;
private String downloadedPath="";
private long downloaded=0;
private File file;
private String returnData=null;
private File cacheDownloadFile;
public DownloadManager(String downloadlink,String fileDestinationPath){
this.downloadlink=downloadlink;
this.fileDestination=fileDestinationPath;
file=new File(fileDestination, Tools.getFileName(downloadlink));
cacheDownloadFile=new File(AppCostants.CHACHE_PATH+Tools.getFileName(downloadlink));
try {
if(cacheDownloadFile.isFile())
downloaded=Tools.getFileSize(cacheDownloadFile);
else
downloaded=0;
Log.d("FILE_DOWNLOAD_TAG_p",downloaded+" <- "+cacheDownloadFile.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
fireOnUpdate(ON_INIT,"init ...");
}
#Override
protected String doInBackground(String... params) {
try {
File dir=new File(fileDestination);
File chacheDir=new File(AppCostants.CHACHE_PATH);
if(!chacheDir.isDirectory())
chacheDir.mkdirs();
if(!dir.isDirectory()){
dir.mkdirs();
}
if(file.exists()) {
Log.d("FILE_DOWNLOAD_TAG","File exist return complete");
return "COMPLETED";//file exist
}
if(!cacheDownloadFile.exists()){
cacheDownloadFile.createNewFile();
}
Log.d("FILE_DOWNLOAD_TAG","LINK "+downloadlink);
URL url=new URL(downloadlink);
HttpURLConnection urlConnection= (HttpURLConnection) url.openConnection();
if(downloaded>0)
urlConnection.setRequestProperty("Range","byte="+downloaded);
urlConnection.connect();
int status = urlConnection.getResponseCode();
InputStream inputStream=urlConnection.getInputStream();
int totalSize=urlConnection.getContentLength();
if(totalSize<=downloaded){
returnData= "COMPLETED";
publishProgress("File checked "+Tools.getFileName(file.getAbsolutePath()));
return returnData;
}
this.downloadedPath=cacheDownloadFile.getAbsolutePath();
byte[] buffer=new byte[1024];
int bufferLength=0;
FileOutputStream fileOutput=new FileOutputStream(cacheDownloadFile);
long d=0;
long starttime=System.currentTimeMillis();
while ((bufferLength=inputStream.read(buffer))>0){
fileOutput.write(buffer,0,bufferLength);
downloaded+=bufferLength;
d+=bufferLength;
//String l=" "+Tools.getFileName(file.getAbsolutePath())+" ( "+Tools.convertMemory(downloaded)+" / "+Tools.convertMemory(totalSize)+" )";
String l=" "+Tools.convertMemory(downloaded)+" / "+Tools.convertMemory(totalSize)+" ( "+getDownloadSpeed(starttime,d)+" )";
publishProgress(l);
if(downloaded>=totalSize){
break;
}
}
Log.d("FILE_DOWNLOAD_TAG","DWONLOADED TO "+downloadedPath+" ("+cacheDownloadFile.length()+")");
fileOutput.close();
if(Tools.fileCopy(file,cacheDownloadFile)){
Log.d("FILE_DOWNLOAD_TAG","file Copied, delete cache");
cacheDownloadFile.delete();
}
returnData="COMPLETED";
} catch (MalformedURLException e) {
returnData=null;
e.printStackTrace();
publishProgress(e.toString());
Log.d("###################",e+"");
} catch (IOException e) {
returnData=null;
e.printStackTrace();
publishProgress(e.toString());
}
return returnData;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
fireOnUpdate(ON_PROGRASS,values[0]);
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
if(s!=null){
fireOnUpdate(ON_COMPLETED,downloadedPath);
}else{
fireOnUpdate(ON_ERROR,"Download failed");
}
}
public interface onUpdateListener{
void onUpdate(int code,String message);
}
public void setOnUpdateListener(onUpdateListener onUpdateListener){
this.onUpdateListener=onUpdateListener;
}
private void fireOnUpdate(int code,String message){
if(onUpdateListener!=null)
onUpdateListener.onUpdate(code,message);
}
private String getDownloadSpeed(long starttime,float totalDownloaded) {
long elapsedTime = System.currentTimeMillis() - starttime;
//byte :
float speed=1000f * totalDownloaded / elapsedTime;
return convert(speed);
}
private String convert(float value){
long kb=1024
,mb=kb*1024
,gb=mb*1024;
if(value<kb){
String speed=(value+"");
speed=speed.substring(0,speed.indexOf('.')+2);
return speed+" B/s";
}else if(value<mb){
value=value/kb;
String speed=(value+"");
speed=speed.substring(0,speed.indexOf('.'));
return (speed)+" KB/s";
}else if(value<gb){
value=(value/mb);
String speed=(value+"");
speed=speed.substring(0,speed.indexOf('.'));
return speed+" MB/s";
}
return "";
}
}
use this code in onClick()
DownloadManager downloadManager = new DownloadManager(url,filepath);
set event
downloadManager.setOnUpdateListener(new DownloadManager.onUpdateListener() {
#Override
public void onUpdate(int code, String message) {
if (code == DownloadManager.ON_COMPLETED) {
}
if(DownloadManager.ON_PROGRASS==code){}
}
});
start download by
downloadManager.execute();
lib setup
compile "commons-io:commons-io:+"
Tools.java
public static long getFileSize(File file) throws IOException {
FileOutputStream fileOutputStream=new FileOutputStream(file);
fileOutputStream.close();
return file.length();
}
public static boolean fileCopy(File dest,File source){
try {
FileUtils.copyFile(source,dest);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
It is really bad idea to download file in main thread.
Use separate Thread for this
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
//your downloading here
}
});
thread.start();
it`s better, but still not so good. There are some problems with it:
1) User know nothing about downloading
So better to show additional layout which overlays screen with progress bar, probably indeterminate if you want to write less code. Then after downloading is finished you just hide your layout.
You can use runOnUiThread inside run method in thread for it.
runOnUiThread(new Runnable() {
#Override
public void run() {
//just hide some popup
//or do what you want after downloading is finished
popupLayout.serVisibility(View.GONE);
}
});
2) If user will do action which re-creates activity/fragment (like changing screen orientaion) with running thread you will get memory leak and probably activity will not know about end of download.
There are few ways to solve this problem:
You can block screen orientation at this screen, at least while downloading. Probably easiest way in your case.
You can use downloading in foreground service. Its really good
practice, but you will have to learn about services.
You can try to interrupt downloading by calling thread.interrupt()
method in onDestroy of your Activity/Fragment
You can use something like rxJava/rxAndroid (so you don not use threads at all, but you need some time for learn rxJava)
UPD
About threads
Not so bad tutorial about threads in android
You can use AsyncTask instead of Thread, but I highly recommend to use threads especially for long operations.
I have a Calendar activity. When the user selects a date, I would like the TextView under the calendar to display all events the user has stored for that date. Under the TextView is a button that takes the user to the activity where they create the event. The button on the Event Creation Activity uses fileOutputStream to save a txt file containing entered information. My issue is reading that info into the TextView on the Calendar Activity. I have the code written for the read, but when I try to point it to the directory created by the fileOutput on EventCreateActivity, I get an error "EventCreateActivity is not an enclosing class." I believe it is an enclosing class, as it has nested classes, correct? What can I do here that requires the least amount of restructuring?
Here is my CalendarActivity:
public class CalendarActivity extends AppCompatActivity {
CalendarView calendar;
Button createEvent;
public static String createEventDate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calendar);
calendar = (CalendarView)findViewById(R.id.calendar);
calendar.setOnDateChangeListener(new CalendarView.OnDateChangeListener(){
#Override
public void onSelectedDayChange(CalendarView view, int year, int month, int dayOfMonth){
createEventDate = (month+"."+dayOfMonth+"."+year);
createEvent.setText("Create Event for "+createEventDate);
File directory = EventCreateActivity.this.getFilesDir().getAbsoluteFile();
File[] dateFile = directory.listFiles();
if (dateFile.length > 0){
fillEventList();
}else{
noEventToday();
}
}
});
createEvent = (Button)findViewById(R.id.eventCreateButton);
createEvent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent toEventCreateActivity = new Intent(CalendarActivity.this, EventCreateActivity.class);
startActivity(toEventCreateActivity);
}
});
}
public void fillEventList (){
TextView eventList = (TextView)findViewById(R.id.eventList);
try {
String message = createEventDate;
FileInputStream fileInput = openFileInput(message);
InputStreamReader inputStreamReader = new InputStreamReader(fileInput);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
StringBuffer stringBuffer = new StringBuffer();
while ((message = bufferedReader.readLine())!=null){
stringBuffer.append(message+"/n");
}
eventList.setText(stringBuffer.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void noEventToday(){
TextView eventList = (TextView)findViewById(R.id.eventList);
eventList.setText("Nothing scheduled for today.");
}
}
here is my EventCreateActivity:
public class EventCreateActivity extends AppCompatActivity {
String textViewText = CalendarActivity.createEventDate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_create);
TextView titleTextView = (TextView)findViewById(R.id.titleTextView);
titleTextView.setText("Create event for "+textViewText);
Button createEventButton = (Button)findViewById(R.id.saveEvent);
createEventButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonSaves();
Intent toCalendarActivity = new Intent(EventCreateActivity.this, CalendarActivity.class);
EventCreateActivity.this.startActivity(toCalendarActivity);
}
});
}
public void buttonSaves () {
TimePicker timePicker = (TimePicker)findViewById(R.id.timePicker);
EditText entryEvent = (EditText)findViewById(R.id.entryEvent);
EditText entryLocation = (EditText)findViewById(R.id.entryLocation);
EditText entryCrew = (EditText)findViewById(R.id.entryCrew);
final String timeHour = timePicker.getCurrentHour().toString();
final String timeMinute = timePicker.getCurrentMinute().toString();;
final String event = entryEvent.getText().toString();
final String location = entryLocation.getText().toString();
final String crew = entryCrew.getText().toString();
try{
FileOutputStream saveNewEvent1 = openFileOutput(textViewText, MODE_WORLD_READABLE);
OutputStreamWriter saveNewEvent2 = new OutputStreamWriter(saveNewEvent1);
try {
saveNewEvent2.write(timeHour);
} catch (IOException e) {
e.printStackTrace();
}
try {
saveNewEvent2.write(timeMinute);
} catch (IOException e) {
e.printStackTrace();
}
try {
saveNewEvent2.write(event);
} catch (IOException e) {
e.printStackTrace();
}
try {
saveNewEvent2.write(location);
} catch (IOException e) {
e.printStackTrace();
}
try {
saveNewEvent2.write(crew);
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getBaseContext(), "Roger Roger", Toast.LENGTH_LONG).show();
}catch(FileNotFoundException e){
e.printStackTrace();
}
Log.i("info","The event is: "+timeHour+timeMinute+event+location+crew);
}
}
Recent study utilizing Asynctask to establish socket connections, but encountered some situation
now I can use to press the button to establish a connection, , but I do not know how to make the button text from "unconnected" to "Connected ".Compile no problem but it can not be executed on the simulator, press the button, I can see a text from "unconnected" to "Connected", but the next second forced off the APP.
The following is my code fragment:
public class MainActivity extends Activity {
public static Button Btn_Wifi,Btn_Power,Btn_Flame;
public static Boolean connected=false;
public static DataOutputStream dataOutputStream = null;
public static DataInputStream dataInputStream = null ;
public static Socket socket;
AsyncTask:
static class SocketTask extends AsyncTask<Void, Void, Void > {
#Override
protected Void doInBackground(Void ... parms) {
try {
socket = new Socket("ip", port);//
dataOutputStream = new DataOutputStream(socket.getOutputStream());//and stream
changeConnectionStatus(true);//change the connection status
}catch (UnknownHostException e) {
}catch (IOException e) {
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
};
Button.OnClickListener:
Button.OnClickListener BtnWifiOnClickListener = new Button.OnClickListener(){
#Override
public void onClick(View view) {
//SocketTask sockettask = new SocketTask();
new SocketTask().execute();
}
};
changeConnectionStatus:
public static void changeConnectionStatus(Boolean isConnected) {
connected=isConnected;//change variable
if(isConnected){//if connection established
Btn_Wifi.setText("connected");
Btn_Power.setEnabled(true);
}else{
Btn_Wifi.setText("unconnected");
Btn_Power.setText("POWER OFF");
Btn_Power.setEnabled(false);
PowerStatus(false);
}
}
Positive solutions
#Override
protected void onPostExecute(Void result) {
changeConnectionStatus(true);
}
you can't touch UI from doInBackground()
you need to use onPostExecute()
move the call of changeConnectionStatus(true) from doInBackground() as following:
#Override
protected void onPostExecute() {
changeConnectionStatus(true);
}
When i click on an item in my listview, I would like to have a new thread start and execute the desired tasks I have defined for it in the Connect2 class, however, as far as I can tell the thread is not starting or showing any indication of as why it isn't starting. If anybody could help diagnose a problem in the code or point me in the right direction to fix this issue I would greatly appreciate it. Thanks!
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_directory);
final ListView fileDirectory=(ListView) findViewById(R.id.DirectoryView);
final ArrayAdapter adapter=new ArrayAdapter(this, android.R.layout.simple_list_item_1, SocketConnection.remoteList);
fileDirectory.setAdapter(adapter);
fileDirectory.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(FileDirectory.this, "The click works", Toast.LENGTH_SHORT).show();
FileDirectory.listItem=i;
new Connect2().execute("");
adapter.notifyDataSetChanged();
}
});
}
public class Connect2 extends AsyncTask<String, String, String>{
#Override
protected String doInBackground(String... params){
runConnectCode();
return null;
}
}
public void runConnectCode(){
String itemTemp=SocketConnection.remoteList.toArray()[FileDirectory.listItem].toString();
SocketConnection.PW.write(itemTemp);
//SocketConnection.DOS.flush();
SocketConnection.currentF.concat("\\"+itemTemp);
SocketConnection.PW.write(SocketConnection.currentF);
//SocketConnection.DOS.flush();
try{
Object object=SocketConnection.OIS.readObject();
SocketConnection.remoteList=(ArrayList<String>) object;
} catch(IOException e){
System.out.println(e);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}//run()
Try to run your thread using runOnUiThread();
Try to create class extend Asynctask and call your code in doinbackground() method like this:
public class Connect2 extends AsyncTask<String , String , String>
{
#Override
protected String doInBackground(String... params) {
runConnectCode();
return null;
}
}
public void runConnectCode ()
{
String itemTemp = SocketConnection.remoteList.toArray() [FileDirectory.listItem].toString();
try {
SocketConnection.DOS.writeUTF(itemTemp);
SocketConnection.DOS.flush();
} catch (IOException e) {
System.out.println(e);
}
try {
SocketConnection.currentF.concat("\\" + itemTemp);
SocketConnection.DOS.writeUTF(SocketConnection.currentF);
SocketConnection.DOS.flush();
} catch (IOException e) {
System.out.println(e);
}
try {
Object object = SocketConnection.OIS.readObject();
SocketConnection.remoteList = (ArrayList<String>) object;
} catch (IOException e) {
System.out.println(e);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
Finally, call this whenever you want:
new Connect2().execute("");
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.