Este post fué posteado originalmente en SAP HANA through the looking Glass.
Si eres un empleado de SAP, por favor siguenos en Jam.
Finalmente creamos un archivo llamado “flights.xsodata” con el siguiente código
Aún cuando Google Glass ya no va más...al menos no para el consumo masivo…Pensé que conectarlo a SAP HANA serviría para poder escribir un buen blog...puesto que después de todo, tenemos uno en el d-shop…así que aquí vamos -;)
Primero, debemos crear un objeto Join y asociar la tabla por MANDT y CARRID. De ahí, seleccionar los siguientes campos como output MANDT, CARRID, CARRNAME, PRICE y CURRENCY.
Luego crear un objeto Aggregation seleccionándo los campos CARRNAME, PRICE (Como columnas agregadas) y CURRENCY. Debemos filtrar el campo CURRENCY por ‘USD’.
Luego, debemos crear un objeto Projection y seleccionar solo PRICE y CARRNAME.
En el objeto Semantics asegúrense de marcar “CROSS CLIENT” como cliente por defecto.
En el objeto Semantics asegúrense de marcar “CROSS CLIENT” como cliente por defecto.
Ahora, cambiemos a la vista SAP HANA Development y creemos un nuevo repositorio. Lo llamaremos“Flights”.
Creamos un proyecto “XS Engine” y también lo llamamos “Flights”. Lo enlazamos con el repositorio “Flights”.
Creamos un archivo vacio llamado “.xsapp”.
Creamos un archivo llamado “.xsaccess” con el siguente código.
.xsaccess |
---|
{ "exposed" : true, "authentication" : [ { "method" : "Basic" } ] } |
Finalmente creamos un archivo llamado “flights.xsodata” con el siguiente código
Flights.xodata |
---|
service { "Blag/FLIGHTS_BY_CARRIER.calculationview" as "FLIGHTS" keys generate local "Id"; } |
Activamos el proyecto y lanzamos nuestro browser...deberíamos ver algo como esto…
La parte de SAP HANA está lista…así que ahora podemos movernos a la parte de Google Glass…
Primer, debemos descargar Android Studio y actualizar el SDK Manager para incluir lo siguiente…API 19 incluyéndo Google Glass Kit Preview.
Creamos un nuevo proyecto y lo llamamo “GLASS_HANA” o cualquier cosa que se les ocurra…
En la siguiente pantalla, quiten el check “Phone and Tablet” y marquen “Glass”. Asegurense de que “Glass Development Kit Preview (API 19) está seleccionado.
Escogemos “Immersion Activity”.
Dejamos el nombre “MainActiviy” y pueden cambiar el Activity Title is quieren....
En el archivo “MainActivity” copien el siguiente código...
MainActivity.java |
---|
package glass.app.com.flightsreport; import com.google.android.glass.media.Sounds; import com.google.android.glass.widget.CardBuilder; import com.google.android.glass.widget.CardScrollAdapter; import com.google.android.glass.widget.CardScrollView; import android.app.Activity; import android.content.Context; import android.media.AudioManager; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import com.android.volley.RequestQueue; import com.android.volley.toolbox.Volley; import android.speech.RecognizerIntent; import android.speech.tts.TextToSpeech; public class MainActivity extends Activity { /** * {@link CardScrollView} to use as the main content view. */ private CardScrollView mCardScroller; private TextToSpeech mTTS; private RequestQueue mQueue; /** * "Hello World!" {@link View} generated by {@link #buildView()}. */ private View mView; @Override protected void onCreate(Bundle bundle) { super.onCreate(bundle); mView = buildView(); mCardScroller = new CardScrollView(this); mCardScroller.setAdapter(new CardScrollAdapter() { @Override public int getCount() { return 1; } @Override public Object getItem(int position) { return mView; } @Override public View getView(int position, View convertView, ViewGroup parent) { return mView; } @Override public int getPosition(Object item) { if (mView.equals(item)) { return 0; } return AdapterView.INVALID_POSITION; } }); // Handle the TAP event. mCardScroller.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { // Plays disallowed sound to indicate that TAP actions are not supported. AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); am.playSoundEffect(Sounds.DISALLOWED); } }); setContentView(mCardScroller); } @Override protected void onResume() { super.onResume(); mCardScroller.activate(); } @Override protected void onPause() { mCardScroller.deactivate(); mTTS.shutdown(); super.onPause(); } /** * Builds a Glass styled "Hello World!" view using the {@link CardBuilder} class. */ private View buildView() { mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() { @Override public void onInit(int status) { } }); final CardBuilder card = new CardBuilder(this, CardBuilder.Layout.TEXT); mQueue = Volley.newRequestQueue(this); final String carrName = getIntent().getExtras().getStringArrayList(RecognizerIntent.EXTRA_RESULTS).get(0); HANAFlightsAPI.getFlightsData(carrName, mQueue, new HANAFlightsAPI.Callback() { @Override public void onFlightsData(HANAFlightsAPI.FlightsData flightsData) { card.setText(flightsData.price); card.setFootnote(flightsData.carrierName); setContentView(card.getView()); } }); return card.getView(); } } |
Creamos un nuevo archivo y lo llamamos “HANAFlightsAPI” y copiamos el siguiente código
HANAFlightsAPI.java |
---|
package glass.app.com.flightsreport; import android.util.Log; import com.android.volley.RequestQueue; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; import org.json.JSONException; import org.json.JSONObject; import android.util.Base64; import java.util.HashMap; import java.util.Map; import com.android.volley.AuthFailureError; import java.net.URI; import java.net.URISyntaxException; public class HANAFlightsAPI { /** * Open Weather Map API Endpoint */ public static final String URL = "http://YourServer:8000/Flights/flights.xsodata/FLIGHTS?$format=json& $filter=CARRNAME%20eq%20"; /** * Object containing qualitative description of weather as well as temperature in Fahrenheit. */ public static class FlightsData { public final String carrierName; public final String price; public FlightsData(String carrierName, String price) { this.carrierName = carrierName; this.price = price; } } public interface Callback { void onFlightsData(FlightsData flightsData); } public static void getFlightsData(String carrierName, RequestQueue queue, final Callback callback) { URI uri = null; try { uri = new URI(carrierName.replaceAll(" ", "%20")); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } queue.add(new JsonObjectRequest(URL + "%27" + uri + "%27", null, new Response.Listener<JSONObject>() { @Override public void onResponse(JSONObject response) { String carrier = ""; String price = ""; try { JSONObject results = (JSONObject) response.getJSONObject("d").getJSONArray("results").get(0); carrier = results.getString("CARRNAME"); price = results.getString("PRICE"); } catch (JSONException e) { e.printStackTrace(); } callback.onFlightsData(new FlightsData(carrier, price)); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e("onErrorResponse", error.getMessage()); } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { HashMap<String, String> headers = new HashMap<String, String>(); String creds = String.format("%s:%s", "SYSTEM", "YourPassword"); String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.DEFAULT); headers.put("Authorization", auth); return headers; } }); } } |
Vamos al segundo archivo build.gradle (el que dice “Module.app”) y agregamos esto...
Module.app |
---|
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.mcxiaoke.volley:library:1.0.+' androidTestCompile 'org.hamcrest:hamcrest-all:1.3' } |
Esto va a agregar la Volley library la cual es una librería HTTP diseñana para hacer que las aplicaciones de networking con Android sean más sencillas y más veloces.
Abrimos el archivo “voice_trigger.xml” y copiamos el siguiente código...
voice_trigger.xml |
---|
<?xml version="1.0" encoding="utf-8"?> <trigger keyword="Flight Report"> <input prompt="Which Carrier?"/> </trigger> |
Abrimos el archivo “strings.xml” y copiamos el siguiente código...
strings.xml |
---|
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Flights Report</string> <string name="glass_voice_trigger">flights report</string> <string name="glass_voice_prompt">which carrier?</string> </resources> |
Abrimos el archivo “AndroidManifest.xml” y copiamos el siguiente código
AndroidManifest.xml |
---|
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="glass.app.com.flightsreport"> <uses-permission android:name="com.google.android.glass.permission.DEVELOPMENT"/> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="Flights Report"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="com.google.android.glass.action.VOICE_TRIGGER"/> </intent-filter> <meta-data android:name="com.google.android.glass.VoiceTrigger" android:resource="@xml/voice_trigger"/> </activity> </application> </manifest> |
Estamos casi listos…necesitamos conectar nuestro Google Glass y asegurárnos de que está en Debug On.
Navegamos hasta “Settings” e ingresamos.
Navegamos hasta “Device info” y lo seleccionamos
Navegamos hasta “Turn on debug” y lo seleccionamos. Debería convertirse en “Turn off debug”
Con eso podremos ser capacer de enlazar nuestro Google Glass con nuestro proyecto en Android Studio. Simplimente lo ejecutamos y lo veremos en Google Glass.
Hacemos click para entrar y veremos la pantalla principal
Di el nombre de una aerolínea como “American Airlines”
Espera y la aplicación se conectará con nuestro ODATA en SAP HANA y mostrará el resultado
Ahora, para no hacerlos pensar que me estoy inventándo esto…intentemos con otra…como “Lufthansa”
Esperen a ver el resultado…
Bueno, no? También pueden preguntar por “Delta Airlines” o “United Airlines”…si preguntamos por algo más, nos dará el resultado del nombre más aproximado o el del valor por defecto.
Estoy lo suficientemente feliz con este pequeño proyecto -;)
Saludos,
Blag.
Development Culture.
No comments:
Post a Comment