Should I use AsyncTask to establish an XMPP connection? - android

I am connecting to an XMPP server in Android using Smack. Here is my code:
static void openConnection() {
try {
if (null == connection || !connection.isAuthenticated()) {
XMPPTCPConnectionConfiguration.Builder configuration = XMPPTCPConnectionConfiguration.builder();
configuration.setHost(SERVER_HOST);
configuration.setPort(SERVER_PORT);
configuration.setServiceName(SERVICE_NAME);
configuration.setUsernameAndPassword(new TinyDB(context.getApplicationContext()).getString("username"), new TinyDB(context.getApplicationContext()).getString("password"));
configuration.setDebuggerEnabled(true);
connection = new XMPPTCPConnection(configuration.build());
connection.setUseStreamManagement(true);
connection.setUseStreamManagementResumption(true);
ReconnectionManager reconnectionManager = ReconnectionManager.getInstanceFor(connection);
reconnectionManager.enableAutomaticReconnection();
reconnectionManager.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
connection.connect();
connection.login();
}
} catch (XMPPException xe) {
xe.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
So when I call openConnection() should I do that in an AsyncTask or is that not necessary? I am a little confused.

You should manage your XMPP(TCP)Connection within an Android Service. The service state (running/stopped) should reassemble the connection state: When the service is running the connection should be established or the service should try to establish the connection (if data connectivity is available). If the service stops, then also disconnect the connection.

When i call openConnection() should i do that in an asynctask or that is not neccesary?
Shortly, YES. Everything related with networking should be moved to another thread to avoid blocking main thread. Hence doInBackground() of AsyncTask runs on another thread, which is where you should call that function.

Yes, as the official documentation points it out:
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.

I chose not to use AsyncTask for my smack project after searching around.
its threading model have been quite different between Android version and need to take care about, also after honeycomb, it is single thread, long blocking this will cause issue on the whole device that also use AsyncTask , xmpp and bosh can cause long blocking up to seconds/minutes
AsyncTask has implicit reference to activity and such a long operation will cause memory issues, or easy memory leakage when exception handling is not proper
AsyncTask 's result will be lost if reference activity got reset, but activity in Android can be reset as easy as a simple device rotation or network configuration change, too many save and restore instance to make this usable as every xmpp operation may be long task

Related

Android Socket, AsyncTask, Handler memory leak

I'm feeling frustrating. After few day, I raise the white flag and ask for help.
I've used this code sample:
https://github.com/sht5/Android-tcp-server-and-client
But every time I try to establish a connection the memory uses is increased by about 500KB, so if the client disconnects and then reconnects without closing the application after many attempts the memory becomes saturated.
I have already tried various methods including
cancel (true) in AsyncTask's doInbackground,
close and force the socket and in, out objects to null
call System.gc ()
but none of this worked.
I'm not sure, but try to invoke AsyncTask as
new InitTCPClientTask().execute(new Void[0]);
instead of
InitTCPClientTask task = new InitTCPClientTask();
task.execute(new Void[0]);

Android: Thread infinite loop / phone overheating

I'm working on a Thread that handles all server connections:
public void run() {
//this initializes Socket and PrintWriter/DataInputStream
connect(server, port);
while(true) {
//queue is a BlockingQueue where I put the messages to send
while(!queue.isEmpty()) s
//COMMUNICATE-WITH-SERVER-CODE
}
}
}
The code works, but after a minute or so, my phone starts overheating and battery goes down fast. I know it's because of the infinite loop.
How can I solve it? I want a Thread which, once started, keeps the connection to the server (so that DataInputStream and PrintWriter won't be initialized every time). And I want the thread to be responsive: when I click a Button it should sent instantaneously a message to the server for processing.
I have implemented a Handler for communicating Thread->Activity. But how can I communicate Activity->Thread?
Any tip would be welcome.
Generally the solution would be to add a polling intervall, ex: sleep the thread for 500ms after each iteration. But in this case there is no need for that, because we do not have to poll a BlockingQueue. From the doc
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
If we use a BlockingQueue, then the queue.pop() call blocks if the queue is empty and remains blocked until an entry is pushed onto the queue. There fore there is no need for looping.
However, we will need to have some sort of mechanism to keep the thread from terminating. Here is a simple example:
public void run() {
try {
while (true) {
handleServerIO(queue.take());
}
}catch (InterruptedException ex) {
... handle ...
}
}

IntentService using ThreadPoolExecutor... recommended or not?

I'm designing an android app that will listen to the incoming SMSs and will handle them in a specific way.
I have a broadcast receiver that receives the message and sends it to an intent service:
Intent serviceIntent = new Intent(context, SMSIntentService.class);
serviceIntent.putExtras(intent.getExtras());
context.startService(serviceIntent);
The purpose of the intent service is to save the SMS to my own DB and then send that message to a server via HTTP POST, evaluate the result and update the app's DB and eventually reply to the sender.
So far everything is good but as there is a chance that a lot of SMS arrive at the same time, I want to decouple the communication with the server putting it in another thread.
So what I'm doing so far is this:
SmsDto sms = smsDataSource.saveSms(new SmsDto(originator, body, timestamp));
SMSProcessingTask task = new SMSProcessingTask(this.getApplicationContext(), sms);
Thread t = new Thread(task);
t.start();
And so far so good, but I don't trust this implementation with a big amount of messages.
So, my question is:
In an intent service, is it recommended to use a ThreadPoolExecutor?
I would end up with something like this:
//in IntentService's onCreate
this.executor = Executors.newCachedThreadPool();
//in onHandleIntent()
executor.execute(task);
What happens if for a period of time no messages are received and the IntentService stops. Will the threads created by it continue running?
I don't know if this approach is the best way to deal with what I'm trying to accomplish.
Thanks
Update:
There is not UI activity at all in this app.
Since the communication with the server can take quite a long time, I want to minimize the processing time of a message, so the next sms in queue is picked up quickly and start being processed.
Ni
No you shouldn't use one. The main reason being that SQlite access is not thread safe so you don't want multiple threads writing to the database at the same time.
Also, if you task happens to update the UI it's not going to work that way.
I really don't understand why you have those tasks : the IntentService already processes its messages off the UI thread.
What you can do is use the submit(Callable) method instead of the execute one.
that way you can get a future object with the data you want to write in the DB and no thread will actually touch it as it not safe like Phillippe said
I used it on a similar way when I needed multiple httprquests to send.
I managed them using SQL DB, so the writing only occur on the onHandleIntent.
while(helper.requestsExists()){
ArrayList<String> requestArr = helper.getRequestsToExcute(3);
//checks if the DB requests exists
if(!requestArr.isEmpty()){
//execute them and delete the DB entry
for(int i=0;i<requestArr.size();i++){
file = new File(requestArr.get(i));
Log.e("file",file.toString());
Future<String> future = executor.submit(new MyThread(file,getApplicationContext()));
Log.e("future object", future.toString());
try {
long idToDelete = Long.parseLong(future.get());
Log.e("THREAD ANSWER", future.get() + "");
helper.deleteRequest(idToDelete);
} catch (InterruptedException e) {
Log.e("future try", "");
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
executor.shutdown();
secondly the intentService will not stop until the onHandleIntent is done and even if so, the threads will continue running until they've done their job

Should I launch a Thread to parse some xml?

I'm kinda new to android development, but i'm trying to make a xml parser. I've been using android.sax library, following some tutos, and this works great.
One thing that is making me sceptical, is that I don't actually launch the parser in a separate thread, I just use a handlers to communicate between my parser and my main activity.
Should I parse in a Thread ?
Here's my main activity code :
tv = (TextView)findViewById(R.id.tv);
try {
URL url = new URL("https://www.googleapis.com/shopping/search/v1/public/products?key=AAAAABBBBBCCCCDDDEEEEFFF&country=FR&restrictBy=gtin=5030999075254&alt=atom");
XMLHandler xHandler = new XMLHandler();
Feed feed = xHandler.parse(url.openStream());
if(feed.getTotalResults()==0 || feed.getItems() == null || feed.getItems().isEmpty()) {
Log.w("XMLPARSENull", "No items
}
else {
tv.setText(feed.getTotalResults()+" " + feed.getItemsPerPage() + " " + feed.getStartIndex() + " " + feed.getTitle());
Iterator<Product> it = feed.getItems().iterator();
while(it.hasNext()) {
Log.w("XMLPARSEFeed",it.next().getName());
}
}
} catch(Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.e("XMLPARSEException", "ERROR",e);
}
I don't think that it's the parsing so much as the network operation, as any network request should not be performed in the UI thread. You can either spawn a new Thread or an AsyncTask to perform your network request. Here are some links to help:
AsyncTask
Painless threading
Expensive operations
Designing for responsiveness
Thread documentation
Handler documentation
A simple answer:
If you have connections in your main ( UI ) thread, the user interface will become frozen whilst the thread is used to download the information and parse it. It takes some time for a connection so it may appear to freeze.
Apart from that, android 4.0 now does not actually allow you to call HTTP requests from this thread, it will throw an error which will be seen in logcat before crashing.
It is best practise to use an Async Task here, here is some more information on that.
Information on Async Tasks!
Yes, it is imperative that you move your parsing into a background thread, particularly if your XML is being streamed across the network; otherwise your app is likely to be killed off by the system for blocking the main thread.
You don't have to use a raw Thread, though; Android provides things like ASyncTask to make it a bit easier.
Everything which isn't related to direct interaction with GUI should be moved to separate thread, prefferably AsyncTask if you need interaction with GUI from that thread since Android won't allow accessing GUI from regular Thread class.
http://developer.android.com/reference/android/os/AsyncTask.html

How to abort LocalServerSocket.accept

How to abort/interrupt a LocalServerSocket waiting, in a background thread, for a connection in method LocalServerSocker.accept() ?
I've tried to call close() method from another thread, but it does not seem to work.
There is a ticket opened for it in Android project: http://code.google.com/p/android/issues/detail?id=29939.
Seems the problem is confirmed by Google, as the first comment is:
i think we should rewrite this to use the same underlying libcore
stuff, and get the interruption behavior for free.
The workaround can be to send a custom shutdown command to the LocalServerSocket from another thread to unblock accept.
Instead of localSocket.close, use this: (requires API 21+)
try {
Os.shutdown(localSocket.fileDescriptor, OsConstants.SHUT_RDWR)
} catch (e: ErrnoException) {
if (e.errno != OsConstants.EBADF) throw e // suppress fd already closed
}

Categories

Resources