quinta-feira, 22 de outubro de 2015

Consuming a CFapi generated API with Android

Hello folks! Today I am going to show you how to consume an API (dynamically created with CFapi) in an Android application.

I have created the API named "health" with CFapi (http://CFapi.riaforge.org) based on a database view called "hospitals". The view contains three fields: Nome, Latitude and Longitude (sorry, I left field name as "Nome", the word in portuguese for name).

After filling the CFapi main form and clicking the "Generate API" button, I was ready to deploy my instant generated API "Health" to my server on the Internet.

You can check it out in the following address:


By clicking in the above link, you will see a real-time generated REST/JSON flow coming from RAM memory that was previously filled by a database query on view "hospitals".

This JSON shows a list of some of the hospitals available in the city of Rio de Janeiro.

Now, the idea is to show here how to consume this JSON in an Android application.

In out project, the first thing to do is to define a class to receive the objects from JSON. Lets call it HospitalDTO:

package com.example.androidcfapiconsumer;

public class HospitalDTO
{

   String name = "";
   String latitude = "";
   String longitude = "";
  
   public String getName()
   {
      return name;
   }
   public void setName(String name)
   {
      this.name=name;
   }
   public String getLatitude()
   {
      return latitude;
   }
   public void setLatitude(String latitude)
   {
      this.latitude=latitude;
   }
   public String getLongitude()
   {
      return longitude;
   }
   public void setLongitude(String longitude)
   {
      this.longitude=longitude;
   }  
}
 


Then, we have to create a webService consumer. So we are going to add a new class called HospitalWS:


// REST WebService consumer
package com.example.androidcfapiconsumer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.net.Uri;
import android.util.Log;

public class HospitalWS
{

   private static String URL="";
   private static String ENDPOINT="";
   private static int timeout=10000;

   public ArrayList<HospitalDTO> getHospitals(String token)
   {
      URL="http://www.tradeteller.com.br";
      ENDPOINT="/health/api/v1/rest/hospitals.cfm";

      ArrayList<HospitalDTO> hospitals=new ArrayList<HospitalDTO>();
      String result="";

      try
      {
         HttpParams httpParameters=new BasicHttpParams();
         int timeoutConnection=timeout;
         HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
         int timeoutSocket=timeout;
         HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);

         // Define inputStream
         InputStream inputStream=null;

         // Create http client.
         HttpClient httpclient=new DefaultHttpClient(httpParameters);

         // Define input parameters values.
         Uri.Builder b=Uri.parse(URL).buildUpon();
         b.path(ENDPOINT);
         b.appendQueryParameter("token", token);
         b.appendQueryParameter("pretty", "");
         b.appendQueryParameter("filter", "");
         String url=b.build().toString();

         // Create the GET and set URL.
         HttpGet httpget=new HttpGet(url);

         // Define data type.
         httpget.setHeader("Accept", "text/json");

         try
         {
            // Send the URL request, using GET.
            HttpResponse httpResponse=httpclient.execute(httpget);

            // Receive response as "inputStream".
            inputStream=httpResponse.getEntity().getContent();

            String converted=convertInputStreamToString(inputStream);

            // Check if http response code is 200 (OK).
            if (httpResponse.getStatusLine().getStatusCode() == 200)
            {
               result=converted;

               // Parse JSON.
               hospitals=parseJSONString(result);
            }
            else
            {
            }

         }
         catch (Exception g)
         {
            g.printStackTrace();
         }
      }
      catch (Exception h)
      {

      }

      return hospitals;
   }

   private ArrayList<HospitalDTO> parseJSONString(String result)
   {
      ArrayList<HospitalDTO> hospitals=new ArrayList<HospitalDTO>();

      JSONArray ja=null;

      try
      {
         ja=new JSONArray(result);
      }
      catch (JSONException e)
      {
         e.printStackTrace();
      }

      for (int i=0; i < ja.length(); i++)
      {

         JSONObject oneObject=null;

         try
         {
            oneObject=ja.getJSONObject(i);
         }
         catch (JSONException e)
         {
            e.printStackTrace();
         }

         // Pulls items from the array.
         try
         {
            String name=oneObject.getString("NOME");
            String latitude=oneObject.getString("LATITUDE");
            String longitude=oneObject.getString("LONGITUDE");

            HospitalDTO hospital=new HospitalDTO();
            hospital.setName(name);
            hospital.setLatitude(latitude);
            hospital.setLongitude(longitude);
            hospitals.add(hospital);

         }
         catch (JSONException e)
         {
            e.printStackTrace();
         }

      }

      return hospitals;

   }

   private static String convertInputStreamToString(InputStream inputStream) throws IOException
   {
      BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));

      int c;
      StringBuilder response=new StringBuilder();

      while ((c=bufferedReader.read()) != -1)
      {
         response.append((char) c);
      }
      String result=response.toString();
      inputStream.close();

      return result;

   }

}

Finally,copy and paste the code below to MainActivity.java:


package com.example.androidcfapiconsumer;

import java.util.ArrayList;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import com.example.projetomapa.R;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;

public class MainActivity extends FragmentActivity
{

   ArrayList<HospitalDTO> hospitals=new ArrayList<HospitalDTO>();
   GoogleMap supportMap;

   @Override
   protected void onCreate(Bundle savedInstanceState)
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);

      int resultCode=GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());

      if (resultCode == ConnectionResult.SUCCESS)
      {

         FragmentManager fmanager=getSupportFragmentManager();
         Fragment fragment=fmanager.findFragmentById(R.id.map);
         SupportMapFragment supportmapfragment=(SupportMapFragment) fragment;
         supportMap=supportmapfragment.getMap();

         supportMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);

         supportMap.setMyLocationEnabled(true);

         LatLng latlng=new LatLng(-22.910509, -43.203932);

         CameraPosition cameraPosition=new CameraPosition.Builder().target(latlng).zoom(10).build();
         supportMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

      }
      else
      {
         try
         {
            int RQS_GooglePlayServices=1;

            GooglePlayServicesUtil.getErrorDialog(resultCode, this, RQS_GooglePlayServices);
         }
         catch (Exception erro)
         {
            finish();
         }
      }

      // Start webService consumption.
      showHospitals();

   }

   private void showHospitals()
   {
      new Thread()
      {
         public void run()
         {

            try
            {
               String token="8FBC592A-9899-998C-906EFD25C55AAA97";

               HospitalWS hospitalWS=new HospitalWS();
               hospitals=hospitalWS.getHospitals(token);

               Bundle bundle=new Bundle();
               bundle.putString("message", "ok");

               Message message=new Message();
               message.setData(bundle);
               messageHandler.sendMessage(message);

            }
            catch (Exception e)
            {
               e.printStackTrace();
            }

         }
      }.start();

   }

   public Handler messageHandler=new Handler()
   {
      public void handleMessage(Message message)
      {
         String result=(String) message.getData().getString("message");

         if (result == "ok")
         {
            MarkerOptions markeroptions=new MarkerOptions();

            for (HospitalDTO item : hospitals)
            {

               // Draw markers on the map.
               markeroptions.position(new LatLng(Double.valueOf(item.latitude), Double.valueOf(item.longitude)));
               markeroptions.title(item.name);
               markeroptions.draggable(false);

               supportMap.addMarker(markeroptions);

            }

         }
      }
   };

}

Of course, AndroidManifest.xml must be altered to:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.projetomapa"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <permission
        android:name="com.example.projetomapa.permission.MAPS_RECEIVE"
        android:protectionLevel="signature" />

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-feature
        android:glEsVersion="0x00020000"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.androidcfapiconsumer.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="AIzaSyB_i5ss8XwMWOXTDVj50A8jgdecWhH29X0" />
    </application>

</manifest>

And also this small definition on strings.xml file:


<string name="app_name">Android CFapi consumer</string>



Basically what we are doing here is starting an application with a standard Google Map, then we call an asynchronous task to consume our "Health" JSON API entry-point. When its finished, the hospitals are shown on the map.

The result can be seen in the following screen capture:






The complete Android CFapi consumer example can be downloaded here.



Nenhum comentário:

Postar um comentário