If you are an SAP Employee, please follow us on Jam.

Even when Google Glass is no more…at least not for individuals…I thought that connecting it to SAP HANA would make for a nice blog…because after all we have one at the d-shop…so here we go -;)


First, we need to create a Calculation View and call it “FLIGHTS_BY_CARRIER”. It will be composed of two tables, SCARR and SFLIGHT.

First, we need to create a Join object and link the table by MANDT and CARRID. From here select the following fields as output MANDT, CARRID, CARRNAME, PRICE and CURRENCY.

Then create an Aggregation object selecting the fields CARRNAME, PRICE (As Aggregated Column) and CURRENCY. Filter the CURRENCY field by ‘USD’.

Then create a Projection object and select only PRICE and CARRNAME.

On the Semantics object make sure to select “CROSS CLIENT” as the Default Client.


Now, switch to the SAP HANA Development View and create a new repository. Call it “Flights”.

Create a new “XS Engine” project and call it “Flights” as well. Link it to the “Flights” repository.

Create an empty “.xsapp” file.

Create a file called “.xsaccess” with the following code.



“exposed” : true,

“authentication” : [ { “method” : “Basic” } ]


Finally create a file called “flights.xsodata” with the following code


service {

          “Blag/FLIGHTS_BY_CARRIER.calculationview” as “FLIGHTS” keys generate local “Id”;


Activate your project and launch it on your browser, you should see something like this…


The SAP HANA part is done…so we can move into the Google Glass part…

First, download Android Studio and update your SDK Manager to include the following…API 19 including Google Glass Kit Preview.


Create a new project and call it “GLASS_HANA” or whatever you fancy…


On the next screen, uncheck “Phone and Tablet” and check “Glass”. Make sure that “Glass Development Kit Preview (API 19) is selected.


Choose “Immersion Activity”.


Leave the “MainActiviy” name and change the Activity Name if you want.


On the “MainActivity” file copy the following code

Main Activity

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;


    protected void onCreate(Bundle bundle) {


        mView = buildView();

        mCardScroller = new CardScrollView(this);

        mCardScroller.setAdapter(new CardScrollAdapter() {


            public int getCount() {

                return 1;



            public Object getItem(int position) {

                return mView;



            public View getView(int position, View convertView, ViewGroup parent) {

                return mView;



            public int getPosition(Object item) {

                if (mView.equals(item)) {

                    return 0;


                return AdapterView.INVALID_POSITION;



        // Handle the TAP event.

mCardScroller.setOnItemClickListener(new AdapterView.OnItemClickListener() {


            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);







    protected void onResume() {





    protected void onPause() {






     * Builds a Glass styled “Hello World!” view using the {@link CardBuilder} class.


    private View buildView() {

        mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {


            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() {


            public void onFlightsData(HANAFlightsAPI.FlightsData flightsData) {






        return card.getView();



Create a new file and call it “HANAFlightsAPI” and copy the following code


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



        queue.add(new JsonObjectRequest(URL + “%27” + uri + “%27”, null,

                new Response.Listener<JSONObject>() {


                    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) {



callback.onFlightsData(new FlightsData(carrier, price));


                }, new Response.ErrorListener() {


            public void onErrorResponse(VolleyError error) {

Log.e(“onErrorResponse”, error.getMessage());


        }) {


            public Map<String, String> getHeaders() throws AuthFailureError {

                HashMap<String, String> headers = new HashMap<String, String>();

                String creds = String.format(“%s:%s”, “YourUserName”, “YourPassword”);

                String auth = “Basic ” + Base64.encodeToString(creds.getBytes(), Base64.DEFAULT);

headers.put(“Authorization”, auth);

                return headers;





Go the second build.gradle file (the one that says “Module.app”) and add this…


dependencies {

    compile fileTree(dir: ‘libs’, include: [‘*.jar’])

    compile ‘com.mcxiaoke.volley:library:1.0.+’

    androidTestCompile ‘org.hamcrest:hamcrest-all:1.3’


This will add the Volley library which is an HTTP library designed to make Android apps networking easier and faster.

Open the file “voice_trigger.xml” and copy the following code


<?xml version=”1.0″ encoding=”utf-8″?>

<trigger keyword=”Flight Report”>

    <input prompt=”Which Carrier?”/>


Open the file “strings.xml” and copy the following code


<?xml version=”1.0″ encoding=”utf-8″?>


    <string name=”app_name”>Flights Report</string>

    <string name=”glass_voice_trigger”>flights report</string>

    <string name=”glass_voice_prompt”>which carrier?</string>


Open the file “AndroidManifest.xml” and copy the following code


<?xml version=”1.0″ encoding=”utf-8″?>

<manifest xmlns:android=”http://schemas.android.com/apk/res/android


    <uses-permission android:name=”com.google.android.glass.permission.DEVELOPMENT”/>

    <uses-permission android:name=”android.permission.INTERNET”/>




        android:label=”Flights Report”>

        <activity android:name=”.MainActivity”>


                <action android:name=”com.google.android.glass.action.VOICE_TRIGGER”/>








We’re almost ready…we need to connect our Google Glass and make sure it’s on Debug On.

Navigate to “Settings” and enter it.


Navigate to “Device info” and click it


Navigate to “Turn on debug” and click it. It should become “Turn off debug”


With that we will be able to link our Google Glass to our Android Studio project. Simply run it and you will see this on the Glass.


Click to enter it and you will see the main screen


Say a carrier name like “American Airlines”


Wait and the application will connect to our SAP HANA OData and display the result


Now, to not make you believe that I’m just making this up…try another one…like “Lufthansa”


Wait to see the result…


Cool, huh? You could also ask for “Delta Airlines” or “United Airlines”…if you ask for something else, it might give you back the result for the most approximate name or just the default one.

I’m happy enough with this little project -;)

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply