20 September, 2014

Could not establish secure channel for SSL/TLS with authority

There is a WCF service in a test machine and it uses https. It has a self signed certificate for the machine dns.

Every time I called the web service it returned an error
Could not establish trust relationship for SSL/TLS secure channel

The binding and endpoint configuration in the client and the server were OK and i could even make the service call successfully through soapUI (a free tool to test web services).

In the end, since the certificate was self signed, and not on my machine, I had to install the certificate in my machine for the call to work.

Install certificate using Windows:
  1. - open Internet explorer
  2. - open the service site
  3. - click on the red "Certificate error" box right next to the address bar
  4. - choose view certificates
  5. - install certificate
  6. - next, select "Place all certificates in the following store"
  7. - Select Trusted Root Certification Authorities
  8. - accept everything and you're done.

12 September, 2014

Sharing a local photo to Facebook on Android using Facebook SDK

Most of the steps depicted here can be found on Facebook Developers page but sharing a photo while showing the share dialog isn't fully documented.

Download SDK

Download the Facebook SDK and extract it.

Setup Workspace

Add the Facebook SDK project to your workspace and link the library to your project.

Register App on Facebook

Follow these steps to create a Facebook app and get the Application Id.

Android Manifest

Add these elements to your app Manifest file inside the application element and replace the 123456789456789 of the provider with the application id you got from the facebook page.
<activity android:name="com.facebook.LoginActivity" android:label="@string/app_name" android:theme="@android:style/Theme.Translucent.NoTitleBar" />

<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/>

<provider android:authorities="com.facebook.app.NativeAppCallContentProvider123456789456789" android:name="com.facebook.NativeAppCallContentProvider" android:exported="true" />
The provider was what I was missing from my solution resulting on the photo being published without showing any dialog to the user.
Don't forget to add the facebook_app_id string in your string.xml file.

Initialization

I ended up using Android Simple Facebook library to login the user if necessary since it's really easy to use. 
private Permission[] permissions = new Permission[] { Permission.PUBLISH_ACTION };

public initialization(String appId, String appNamespace, Bundle savedInstanceState) {
 // Facebook SDK initialization
 uiHelper = new UiLifecycleHelper(this, null /*statusCallback*/);
 uiHelper.onCreate(savedInstanceState);

 // Simple Facebook Library initialization
 SimpleFacebookConfiguration configuration = new SimpleFacebookConfiguration.Builder().setAppId(appId).setNamespace(appNamespace).setPermissions(permissions).build();
 SimpleFacebook.setConfiguration(configuration);
}
Use the status callback to get Facebook session status
It is also needed to attach some lifecycle events to these libraries.
@Override
protected void onSaveInstanceState(Bundle outState) {
 super.onSaveInstanceState(outState);
 uiHelper.onSaveInstanceState(outState);
}

@Override
protected void onResume() {
 super.onResume();
 uiHelper.onResume();
 mSimpleFacebook = SimpleFacebook.getInstance(activity);
}

@Override
protected void onPause() {
 super.onPause();
 uiHelper.onPause();
}

@Override
protected void onDestroy() {
 uiHelper.onDestroy();
 super.onDestroy();
}

Login user

Before actually posting the user is requested to be logged in and authorize the app. Since we're using the Facebook SDK it requires the Facebook App to be installed on the device. Since the user will already be logged in the Facebook App this post will not request the user to login again. The first post will, however, request permission for your app to post in the user timeline.
As stated above, I've used Simple Facebook library for login.
public void checkFacebookLogin(final File photo) {
 if (facebook.isLoggedIn()) {
  postPhoto(photo);
 } else {
  facebook.logIn(new OnLoginListener() {

   @Override
   public void onFail(String result) {}

   @Override
   public void onException(Throwable exception) {}

   @Override
   public void onThinking() {}

   @Override
   public void onNotAcceptingPermissions(Type type) {}

   @Override
   public void onLogin() {
    postPhoto(photo);
   }
  });
 }
}
On production code you should actually handle the other events.

Post Photo

Actually post the photo.
public void postPhoto(File photo) {
 if (FacebookDialog.canPresentShareDialog(this, FacebookDialog.ShareDialogFeature.PHOTOS)) {
  FacebookDialog shareDialog = new FacebookDialog.PhotoShareDialogBuilder(this).addPhotoFiles(Arrays.asList(photos)).build();
  uiHelper.trackPendingDialogCall(shareDialog.present());
 }
}
Since the WebDialog provided by the Facebook SDK doesn't post photos it looks like we're stuck with this method.

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.