Request a non-blocking server AsyncTask Android Studio? - android

I'm developing my first robust App in Android Studio is an application that communicates with a remote database, for this I am using the AsyncTask class, also made the request in a separate thread, all this I have already done, the question is that I am using a DrawerLayout and every time a menu item is selected, this gets stuck while the data request to the server is done, as I do to make such request is made the one you see DrawerLayout be hidden.
This is how I am running the AsyncTask class.
BD = new TaskExecuteHttpHandler(service, parametros, CONTEXTO);
String resultado="";
try {
resultado = BD.execute().get();
} catch (ExecutionException e) {
e.printStackTrace();
}
I appreciate the help.

Related

Should I use AsyncTask to establish an XMPP connection?

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

android while loop wait for server response using parse server

I developed an android turn based game and so far I can make the first move but when I want the user would wait for the second player to play the app crashes.
What I tried to do is when the player finishes his move I call a function like this:
public void TheThread()
{
boolean fy=false;
while(!fy)
{
if(CheckMove2())
fy=true;
}
}
The checkmove2 function connects the parse table and check if is there a turn and return boolean.
I beleive this is not the right way to do it,thanks for your help.
Edit:
ChecKmove2() function:
private boolean CheckMove2() {
fx=false;
ParseQuery query = new ParseQuery("serverturn");
query.whereEqualTo("Receiver", Sender);
query.getFirstInBackground(new GetCallback() {
public void done(ParseObject updatePO, ParseException ParseError) {
if(ParseError == null){
fx=true;
String objID;
x=updatePO.getInt("x");
y=updatePO.getInt("y");
try {
updatePO.delete();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
///here comes the game algorithm.
if(fx)
return true;
return false;
}
Edit: the app not crashes its just stop and alert: "The app is not responding" and then asks if I want to wait or close the app.The checkmove function works perfectly I checked it with other devices,the problem is to use this checkmove function in a while loop so the user would wait for the opponent turn.
Your application is crashing because in that scenario you've caused an endless loop (if there are no other moves waiting). So the OS will, most likely force close your application because it thinks its become unresponsive.
What you're better off doing is this:
Create a background service with an AyncTask to check for other players moves at specific intervals (10 - 15 mins maybe?)
Once a move is found. Alert the player to it by using a Notification which would link to your app via an Intent
As a side note, you should always use background threads/async tasks etc to talk to networks.
On your place i would do next:
In parse cloudCode afterSave or beforeSave of the object you are waiting for, send a socket message to your app when the needed object is updated. For example using pubnub.com
I think this is a decent solution, but running some loopy checking logic seemes so unprofessional.
In general it works like this:
two players subscribe to a channel
when one finishes move, from cloud code send a message to this
channel
catch it in your app.
The message can trigger update from parse or can contain the needed data itself.

Unable to connect to Tridion Core Service from an Android client

I am developing an Android app for connecting to Tridion 2011 SP1 Core Service.
So far I have created Android WS Stubs from the core service wsdl using wsclient.
Imported those stubs, which allow access to all the core service methods.
I can now authenticate to Tridion via the Android application but as soon as I try to perform even the most basic of web service calls, such as getApiVersion(), I get the error:
ReflectionHelper*java.lang.NoSuchFieldException: GetApiVersionResult.
I was wondering has anyone else managed to create a java android app that communicates with the Core Service?
Interestingly enough, if I run the code as a java application, using wsimport stubs everything works a treat.
Any help appreciated. For reference here is a code snippet:
To connect to Tridion:
class TridionConnect extends AsyncTask<String, Integer, String> {
// Called to initiate the background activity
#Override
protected String doInBackground(String... statuses) {
try {
Authenticator.setDefault(new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("username", "password".toCharArray());
}
});
url = new URL("http://tridion-server/webservices/CoreService2011.svc?wsdl");
System.out.println(String.format("Get Service"));
service = new CoreService2011();
System.out.println(String.format("Get Client"));
client = service.getBasicHttp();
return "Authenticated To Tridion";
} catch (Exception e) {
Log.e("Authentication failure", e.toString());
e.printStackTrace();
return "Failed to authenticate";
}
}
// Called when there's a status to be updated
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
// Not used in this case
}
// Called once the background activity has completed
#Override
protected void onPostExecute(String result) { //
Toast.makeText(FullscreenActivity.this, result, Toast.LENGTH_LONG).show();
area.setText("Authenticated to Tridion OK");
}
}
To get the ApiVersion
client.getApiVersion();
UserData currentUser = client.getCurrentUser();
System.out.println(String.format("'%s' %s", currentUser.getTitle(), currentUser.getId()));
Frank,
It is not possible for a couple of reasons.
If you use wsimport to create the coreservice proxy it will use the javax library, which exists in the JRE. However Dalvik implements only a subset of the javax library which means this approach is impossible in the Android environment.
I then looked at Ksoap2 tools for creating the proxy. This seemed to work OK, in as much as it did create a proxy, however it did not match the coreservice so I was unable to authenticate. I didn't get any further with this approach beyond examining the JRE proxy v Ksoap2 proxy. They were quite different.
At this point I took a step back, had a cup of tea and re-engineered the approach.
I created a c# REST service to sit between the android app and the core service.
This approach seemed a bit complex, but it offers lots of advantages. Lots of the spade work can be done in the REST service, which will be much quicker than similar code on a tablet or phone.
Secondly the REST service sits on the same server as the CMS/CoreService so the comms is quicker and you can make the REST requests from the android app much lighter.
I have got the application to the point where you can authenticate to Tridion, select a publication, and components that is then rendered in a dynamic layout ready for update/save/publish.
The one big downside of this approach is that the REST service 'should' be stateless so superficially you have to authenticate to the coreservice for every request. Of course I don't do that, but you have to come up with some alternative approach Oauth, shared secret etc.
In initial tests this approach has seemed to be fairly slick on an android device.

One "application", multiple packages, database synchronisation

Summary: synchronisation of multiple SQLite databases with server side sequentially.
I'm working on an Android application that is bound to be modular: we have a launcher that fires off intents, based on user choice, to start different application modules (separate installable packages). As it is now, each module has its own SQLite database and that works fine. The task I'm assigned to requires making data synchronisation between handheld and server side (SQL Server 2008 R2) using MS Sync Framework 4.0 (currently October CTP). I had developed android lib according to Sync Framework specs and that works too.
The issue I have is that because of this loosely coupled design (and some other restrictions) I need to have a button in launcher, that forces all modules to synchronise their databases one-by-one (order doesn't matter for now).
My current approach is to have an abstract BroadcastReceiver & Service (I only now discovered IntentService) classes that are inherited in each modules. So in launcher I broadcast intent, each module picks it up using customized BroadcastReceiver and syncs its database using, again, customized Service... In parallel. I have checked ordered broadcasts, but as I have a service doing the actual work it doesn't really help. The only other way I can currently think of is to have a system-wide mutex and use it to lock sync call in every service.
This is my first Android related task so there probably is a better way to solve this, I wouldn't run from redesigning synchronisation part if that makes our teams future life a bit easier.
[EDIT] So it looks like Java doesn't support named mutexes.
[EDIT2] By modules (or separate installable packages) I meant different APK for each module. So when starting a module you actually start a new process for it.
Using 'synchronized' you can implement mutex in java as below. This is a very minimal example.
private final Object mutex = new Object();
...
synchronized (mutex) {
if (myCondition) {
try {
mutex.wait(n);
} catch (XYZException e) {
throw new PQRException(“Wait() issue!”, e);
}
}
}
...
At the end I had to implement global lock using server socket like this:
ServerSocket mServerSocket;
/**
* Simulates global locking using server socket
* #return If lock was successful
*/
private synchronized boolean lock() {
try {
Log.v(serviceName, "Trying to acquire a lock...");
// any port from 49152 through 65535 should work
mServerSocket = new ServerSocket(51515);
return true;
} catch (IOException ioe) {
return false;
}
}
/**
* Simulates global unlocking
*/
private synchronized void unlock() {
try {
Log.v(serviceName, "Releasing a lock.");
if (mServerSocket != null) {
if (!mServerSocket.isClosed()) {
mServerSocket.close();
}
mServerSocket = null;
}
} catch (IOException e) {
e.printStackTrace();
}
}

Android - Downloading data from the internet >> catch connection errors

In my app i connect to a server, which responds with an xml. I parse it with the SAX Parser, and get the data.
The question is:
What is the best way to handle connection issues?
(At this moment if there is no internet connection available the app simply continues showing the ProgressDialog i implemented)
So you basically do (Pseudo code)
ProgessDialog pd = new ProgressDialog(this).show();
Sax.parseStuff();
pd.dismiss();
In this case, wrap the parsing stuff and cancel the dialog on Exception
ProgessDialog pd = new ProgressDialog(this).show();
try {
Sax.parseStuff();
}
finally {
pd.dismiss(); // or cancel
}
You can also do a try { .. } catch (XYZException e ; pd.cancel(); throw e) if you want to process the Exception in a different layer of your app.
As well as following the suggestion of Heiko Rupp, you can also check for the availability of a network connection prior to performing your download. See my post on the subject.

Categories

Resources