Android- posting data to an api on a background thread

In my journey learning android, i came across the need to finally spin a thread. I am calling out to an api, and need to send some post data, as well as of course, get a response. i read all sorts of ways to handle this from running a thread/runnable to the seemingly preferred AsyncTask.

I’m opting for the later, but wanted to jot some things about how this works, given i am not a Java developer and the syntax of the AsyncTask threw me for a loop.

Setup

The basics work like this:

  1. extend the AsyncTask class
  2. override doInBackground, onProgressUpdate, onPostExecute methods in your AsyncTask…there is also a onCancelled, and few others
  3. create a new instance of your AsyncTask class
  4. fire off your new thread: yourClassInstance.execute();
  5. if you need to, you can cancel the thread’s task: yourClassInstance.cancel();

My project has a feature that necessitates the application call home a la an api for the latest published version of the app. For this to work, our api expects two variables: “platform” (“Android” or “iOS”), and a boolean tablet identification (“isTablet”) to differentiate the phone vs tablet os publications. The server will respond a simple xml feed that states the most current os for that platform and some other useless things for this example.

Syntax

AsyncTask has this interesting syntax with the “” thing. What’s happening here is we are declaring variables for the 3 most important methods we override from an AsyncTask. These variables can be whatever you like. For me, in order of appearance these primitives are :

  1. the variable we are sending into doInBackground
  2. the variable we use for onProgressUpdate
  3. the variable returned to onPostExecute , which is when we return to the main thread

Making it happen…

My application fires up…normally i have a class that’s sole job is to make the versioning query, and compare the apps version string to that of the result, then fire the appropriate event for what it discovered. However for brevity, here’s the gist from the launch activity.Here’s how it all comes together for my  needs:

public class MyAppKeypadActivity extends Activity{	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.launch_activity);
		_checkVersion();              
		// ...some other things
 
	} 
	private void _checkVersion()
	{
		MyAppVersionObject ob = null;
 
		PackageInfo info  = null;
		PackageManager pm = _ctx.getPackageManager();
		String packageName = _ctx.getPackageName();
		try {
			info = pm.getPackageInfo(packageName,0);
		} catch (NameNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
 
 
		if (info != null) {
			try {
 
				_currentLocalVersion = info.versionName; 
 
				Intent i = new Intent(_ctx,MyAppAPIService.class);
				i.putExtra(MyAppAPIService.INTENTTYPE, MyAppAPIService.INTENT_VERSION);
				_ctx.startService(i);
 
 
			} catch (Exception e) {
				//TODO: deal with this exception
			}
		}
	} 
}

in MyAppAPIService class, it goes something like:

public class MyAppAPIService extends Service implements MyAppXMLEventListener{	
	@Override
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);
 
		Context context = getApplicationContext(); 
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
 
 
		Bundle b = intent.getExtras();
		String _tpe = b.getString(MyAppAPIService.INTENTTYPE);
		//..comparing intents
 
		if (_tpe.equals(MyAppAPIService.INTENT_VERSION)) 
		{
			doVersioning();
		}
 
	}
 
	private void  doVersioning()
	{
		VersioningHandler versionhandler = new VersioningHandler();
		versionhandler.execute((Void)null);
	}
 
	private class VersioningHandler extends AsyncTask<Void, Integer, Boolean>
	{
		private boolean _isSuccess = true;
		@Override
		protected Boolean doInBackground(Void... params) {
			String response = null;
	    	HttpClient client = new DefaultHttpClient();
 
	    	HttpPost post  = new HttpPost(getBaseUrl() + "version");
	    	try {
	    		//POST vars to send
				List<NameValuePair> namevaluePairs = new ArrayList<NameValuePair>();
				namevaluePairs.add(new BasicNameValuePair(MyAppAPIService.EXTRA_ISTABLET,"0"));
				namevaluePairs.add(new BasicNameValuePair(MyAppAPIService.EXTRA_PLATFORM,"Android" ));
				post.setEntity(new UrlEncodedFormEntity(namevaluePairs));
 
				Log.d("api",getBaseUrl() + "version");
 
				 // Execute HTTP Post Request
		        ResponseHandler<String> responseHandler=new BasicResponseHandler();
		        response = client.execute(post, responseHandler);
 
	    	} catch (ClientProtocolException e) {
	    		_isSuccess = false;
	        } catch (IOException e) {
 
	        	_isSuccess = false;
 
	        } catch (Exception e) {
	        	_isSuccess = false;
 
			}
 
	    	if (response != null)
	    	{                                
				parseVersionResponseXML(response);//parse the xml response
	    	}else
	    	{
	    		String st = getApplication().getString(R.string.apiErrorSignin).toString();
	    		Intent i = new Intent(MyAppAPIService.API_ERROR);
	    		i.putExtra(EXTRA_MESSAGE, st);
	    		i.putExtra(EXTRA_ERRORCODE, 0);
	    		sendBroadcast(i);
	    	}
			return _isSuccess;
		}
 
		@Override
		protected void onPostExecute(Boolean result) {//result = _isSuccess, returned value of doInBackground
			if (! result) {
 
 
			}
		}
	}     
}

Obviously i pulled some things out , like all the xml parsing, etc. The real meat here is we have an AsyncTask handling all the background work to get the xml, and deal with it. More so, hopefully, an understanding of how AsyncTask makes threading easy…and how we can intercept some of the workings in that thread.

Hope that helps…