27 December, 2013

Java REST API HTTP Helper

To ease up on HTTP calls I've build a helper that takes care of their inner workings.

package com.milagaia.helper;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;

public class HttpHelper {

 protected static final String UTF8 = "UTF-8";
 protected static final String CONTENT_TYPE = "application/json; charset=utf-8";
 
 public InputStream Post(String url, String content, int timeoutMillis) 
   throws ConnectTimeoutException, UnsupportedEncodingException, ClientProtocolException, IOException {

  InputStream result = null;

  DefaultHttpClient httpClient = buildHttpClient(timeoutMillis);
  HttpUriRequest req = buildPost(url, content);

  HttpResponse httpResponse = httpClient.execute(req);

  HttpEntity httpEntity = httpResponse.getEntity();
  result = httpEntity.getContent();

  return result;
 }

 public boolean Put(String url, String content, int timeoutMillis) 
   throws ConnectTimeoutException, UnsupportedEncodingException, ClientProtocolException, IOException {

  DefaultHttpClient httpClient = buildHttpClient(timeoutMillis);
  HttpUriRequest req = buildPut(url, content);

  HttpResponse httpResponse = httpClient.execute(req);

  int statusCode = httpResponse.getStatusLine().getStatusCode();

  return statusCode == HttpStatus.SC_OK;
 }

 public InputStream Get(String url, int timeoutMillis) 
   throws ConnectTimeoutException, UnsupportedEncodingException, ClientProtocolException, IOException {

  InputStream result = null;

  DefaultHttpClient httpClient = buildHttpClient(timeoutMillis);
  HttpUriRequest req = buildGet(url);

  HttpResponse httpResponse = httpClient.execute(req);

  HttpEntity httpEntity = httpResponse.getEntity();
  result = httpEntity.getContent();

  return result;
 }

 public InputStream Delete(String url, int timeoutMillis) 
   throws ConnectTimeoutException, UnsupportedEncodingException, ClientProtocolException, IOException {

  InputStream result = null;

  DefaultHttpClient httpClient = buildHttpClient(timeoutMillis);
  HttpUriRequest req = buildDelete(url);

  HttpResponse httpResponse = httpClient.execute(req);

  int statusCode = httpResponse.getStatusLine().getStatusCode();

  if (statusCode == HttpStatus.SC_OK) {

   HttpEntity httpEntity = httpResponse.getEntity();
   result = httpEntity.getContent();
  }

  return result;
 }

 private DefaultHttpClient buildHttpClient(int timeoutMillis) {

  DefaultHttpClient httpClient = new DefaultHttpClient();
  HttpParams httpParameters = httpClient.getParams();
  HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutMillis);
  HttpConnectionParams.setSoTimeout(httpParameters, timeoutMillis);

  return httpClient;
 }

 private HttpPost buildPost(String url, String content) 
   throws UnsupportedEncodingException {

  HttpPost httpPost = new HttpPost(url);
  ByteArrayEntity baEntity = new ByteArrayEntity(content.getBytes(UTF8));
  baEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, CONTENT_TYPE));
  httpPost.setEntity(baEntity);

  return httpPost;
 }

 private HttpGet buildGet(String url) 
   throws UnsupportedEncodingException {

  HttpGet httpGet = new HttpGet(url);

  return httpGet;
 }

 private HttpPut buildPut(String url, String content) 
   throws UnsupportedEncodingException {

  HttpPut httpPut = new HttpPut(url);
  ByteArrayEntity baEntity = new ByteArrayEntity(content.getBytes(UTF8));
  baEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, CONTENT_TYPE));
  httpPut.setEntity(baEntity);

  return httpPut;
 }

 private HttpDelete buildDelete(String url) 
   throws UnsupportedEncodingException {

  HttpDelete httpDelete = new HttpDelete(url);

  return httpDelete;
 }
}
And when i need more advanced features such as authentication I either extend or make the necessary changes. 
Hope this helps someone else.

05 December, 2013

Stock Me Up! by Coding Buffalo

These last couple of months I've been working with a friend on a new app for managing stock portfolios which we're publishing today in beta form.

The app is called Stock Me Up! and it just reached a point where it's stable and feature rich enough for everyone to use. The beta release is aimed at getting feedback from users to improve the app until it's everything it can be.
Here are some screenshots of the app as it is in version 1.0:




For this project my friend +Daniel Cachapa  and I formed a team called +Coding Buffalo aimed and getting solutions such as this app to the market. I'll keep you posted on new projects.
Anyway, if you're interested in financial stuff or are simply curious to see the app, you can download it here: https://play.google.com/store/apps/details?id=com.codingbuffalo.stockmeup.
The app itself is free with advertising. If you really hate ads there's a plugin to disable them. Please let us know what you think.

For more information visit: http://stockmeup.codingbuffalo.com


22 September, 2013

Serviço Educativo

In the past two and a half months I've been in charge of a new solution called Serviço Educativo. It's main goal is to organize and make readily available information regarding education activities hosted by museums, theaters, gardens, companies, and any other entity providing these kinds of services, in Portugal.

On the 1st of September, the solution went live. We made a backoffice for those entities to add their own information and events, an android app and a windows phone app to browse the available data. In development are still the iOS app and the web page which will be ready before year-end. The solution is free in all app stores, and entities must only contact us to get their credentials, again, for free. More information can be found at http://servicoeducativo.pt. I would like to state again, that this solution is, for now, just available in Portugal.

This project has been a wonderful experience and I would like to thank all those involved. I would like to thank +Filipa Lopes with whom the idea for this project was created, +Eduardo Vieitas , IT People Consulting CEO that made the bet and is funding the whole project and +Nuno Silva who has been in charge of all project communication. I would also like to thank my father, +Alvaro Milagaia, and again +Filipa Lopes and +Nuno Silva who all have been adding the first batch of entities into the system. We're closing in on 200 entities in Continental Portugal, Azores and Madeira. Thank you all very much.

We're now in production and I couldn't be happier. We've had very good feedback in this first month and have great hopes for the future. If you're in Portugal and want to check out which education activities are available near you, go to the app store of your device, search for "Serviço Educativo" and check it out. Oh, and don't forget to leave feedback.

19 June, 2013

Custom fonts in Android (Part 3 of 3) - Memory leaks and FontsHelper

As reported here in issue 9904 there is a memory leak if we call Typeface.createFromAsset() multiple times as the fonts are kept open.
To avoid this problem and to keep from accessing assstes multiple times we'll create FontsHelper, a class that will contain all typefaces needed by the app.

public class FontsHelper {

 public static final String ROBOTO_LIGHT = "fonts/Roboto-Light.ttf";
 public static final String ROBOTO_BOLD = "fonts/Roboto-Bold.ttf";
 public static final String ROBOTO_CONDENSED = "fonts/Roboto-Condensed.ttf";
 
 private static Map fonts = new HashMap();
 
 public static Typeface getTypeFace(Context context, String fontPath) {
  
  if (!fonts.containsKey(fontPath)) {
   
   Typeface font = Typeface.createFromAsset(context.getAssets(), fontPath);
   fonts.put(fontPath, font);
  }
  
  return fonts.get(fontPath);
 }
 
 public static void setFont(View view, Typeface font) {
 
        if (view instanceof ViewGroup) 
  {
            for (int i = 0; i < ((ViewGroup)view).getChildCount(); i++) {
   
                setFont(((ViewGroup)view).getChildAt(i), font);
            }
        } else if (view instanceof TextView) {
  
            ((TextView) view).setTypeface(font);
        }
    }
 
 public static void setFont(Context ctx, TextView view, AttributeSet attrs) {

  TypedArray styleAttrs = context.obtainStyledAttributes(attrs, R.styleable.CustomFontView);
  String customFont = styleAttrs.getString(R.styleable.CustomFontView_customFont);
  setFont(context, view, customFont);
  styleAttrs.recycle();
 }

 public static boolean setFont(Context ctx, TextView view, String fontPath) {

  boolean successful = true;
 
  try {
  
   Typeface tf = AssetsHelper.getTypeFace(ctx, fontPath);
   view.setTypeface(tf);
  } catch (Exception e) {
   
   Log.e(TAG, "Error to get typeface: " + e.getMessage());
   successful = false;
  }

  return successful;
 }
This way we avoid the memory leaks and can further simplify the CustomFontTextView class from the previous post.

public class CustomFontTextView extends TextView {

 public CustomFontTextView(Context context, AttributeSet attrs) {

  super(context, attrs);
  FontsHelper.setFont(context, this, attrs);
 }

 public CustomFontTextView(Context context, AttributeSet attrs, int defStyle) {

  super(context, attrs, defStyle);
  FontsHelper.setFont(context, this, attrs);
 }
 
 public CustomFontTextView(Context context, String fontPath) {
  
  super(context);
  FontsHelper.setFont(context, this, fontPath);
 }
}
With the custom font static variables in FontsHelper and the constructor with a fontPath argument in CustomFontTextView we can also apply the font by code in an easier way.

Custom fonts in Android (Part 2 of 3) - Setting font in xml

The objective is to have the following xml:

<?xml version="1.0" encoding="utf-8"?>
<com.demo.LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:control="http://schemas.android.com/apk/res/com.demo"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <com.demo.CustomFontTextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        control:customFont="fonts/Roboto-Light.ttf" />

</com.demo.LinearLayout>

To enable this we need to declare a custom attribute in values\attrs.xml.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <declare-styleable name="CustomFontView">
        <attr name="customFont" format="string" />
    </declare-styleable>

</resources>
Now we can add the control namespace as seen in the first snippet in line 4.
To read the customFont value and actually apply it to the TextView we're going to extend it and read the new attribute. The CustomFontTextView could be something like this:

public class CustomFontTextView extends TextView {

 public CustomFontTextView(Context context, AttributeSet attrs) {

  super(context, attrs);
  setCustomFont(context, this, attrs);
 }
 
 public void setCustomFont(Context context, TextView view, AttributeSet attrs) {

  TypedArray styleAttrs = context.obtainStyledAttributes(attrs, R.styleable.CustomFontView);
  String customFont = styleAttrs.getString(R.styleable.CustomFontView_customFont);
  setCustomFont(context, view, customFont);
  styleAttrs.recycle();
 }
}
Just like this CustomFontTextView, the same method can be applied to all views. To apply to multiple views inside a complex view check Arnaud's answer in http://stackoverflow.com/questions/9797872/use-roboto-font-for-earlier-deviceshttp://stackoverflow.com/questions/9797872/use-roboto-font-for-earlier-devices.

To avoid having the same path copied all over your xml files you may consider creating styles and put the path there.

<style name="RobotoTextView" parent="android:Widget.Holo.Light.TextView">
 <item name="customFont">fonts/Roboto-Bold.ttf</item>
</style>
And then applying that style in your custom controls:
    <com.demo.CustomFontTextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        style="@style/RobotoTextView" />
On the last part we will focus on a memory leak you may find and how to avoid it.

Custom fonts in Android (Part 1 of 3) - Adding to project and set by code

To use custom fonts in Android add the necessary font files to assets/fonts (you may need to create the assets folder).
To apply them by code use the following snippet:

Typeface font = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Light.ttf");
textView.setTypeface(font);
On the second part of this series we'll apply custom fonts in xml.
UPDATE: Oh, and please don't include unnecessary fonts in the asstes folder as seen above as it will bloat your apk. Thanks.

15 April, 2013

Parcitypate is a Finalist

Hey everyone, just wanted the share my joy in these news.
My team (+Rui Milagaia (me) , +Lara Rodrigues and +Vasco Avillez) passed to the second phase of the Lisbon BIG Apps contest with our project Parcitypate.
Our project was one of the 15 chosen between 206 submitted from 10 countries.
Now, the hard work starts.
Wish me luck

01 April, 2013

Code Writer Helper

When working with MDA developers have a to write a lot of Transformer code. There are two important steps to write good code generation.

First step: write and test the end code to minimize errors.
Step two: write the transformer that will generate that code based on models.

The second step usually takes a lot of time as the developer has to write a lot os boilerplate prefix, suffix code in the transformer. To make sure the generated code is readable he must also write indentation related code.

Enter Code Writer Helper. It's just a very simple tool that accepts the prefix, suffix, empty row, add tab and remove tab strings, and returns the code ready to be pasted in the transformer file.
Everything written in the Original Code box is transformed in real time to the transformed Code box.

You can also creating different configurations by clicking on the "+" on the top right corner.

This was written in WPF and it's available on CodePlex.

Happy transforming.

Let machines to machine work

DRY - Don't Repeat Yourself

Every developer knows this principle, and a lot actually apply it, yet most are confined in the code-related meaning of it.
 "Let no line of code be repeated."

When its time to do documentation of a system or start the implementation of a new one, etc most of us either start from scratch or do a lot of copy paste. In no time, the documentation is dated and incorrect and so are year old systems that don't follow the new company standards. And that's the good perspective, because some systems won't be outdated because the company stops learning and starts its slow descent to failure.

Why must we continue to limit ourselves to the code and spend most of our working time repeating meaningless tasks over and over again.

Take documentation of a web service. The interface changes and lets update the document, it changes again, and again and again and.... why doesn't the document. If it is actually needed let the document be generated from the interface.

Take system deployment. Hopefully most don't have to do it by hand nowadays but some still do.

Whenever a task repeats itself those who repeat it lose a chance to create something new. And those who can't create won't learn. Most tasks can be automated, let your mind wonder and find new ways to automate your work. Let your imagination run wild and you will find something for sure. People are slow and error prone but the potential for madness that we have gives us creativity. Everyone loves doing what they are best at and no one likes to lose, so why keep competing with machines in these meaningless tasks instead of winning at creating new ones.

The creative mind should create. A great company must have its employees do human work. Once a task is done automate it however you can so you won't have to do it again. The future then awaits with new and exciting tasks of learning and creating new things and simply letting machines to machine work