Friday, 22 August 2014

Walgreen's Shopping Experience Now Features Gamification and Augmented Reality

U.S. drugstore Walgreens and digital agency Aisle411 have collaborated to produce a pretty compelling in-store shopping experience that makes use of Google's Project Tango.

It looks like shoppers need to create a list before visiting the store, which seems the only obvious weak point in this solution, before they're then shown a route to all the items they'd like to buy. Personalised special offers are displayed en route.

The gamification aspect looks to be limited to the shopper picking up loyalty points for following the proscribed route, but there's plenty of potential for adding further activities.

Build a set of scales into the trolley and add self scan and it strikes me there'd be no need for a physical checkout either. Here's the video.

More here en Francais, though Chrome does a reasonable job of translating the article into English.

Wednesday, 20 August 2014

Handling Preferences in an Android Application: an Example

While the main function of the Beacon Scanner & Logger app is to scan for and log beacon data, there are a number of functions common to many Android apps that I've needed to implement while putting the app together. I thought I'd document how I implemented some of this functionality in a "cookbook" style, in the hope that it proves useful to someone.

It's entirely possible I've made an omission or a mistake in the following. Please feel free to let me know if you spot anything amiss and in return I promise to bestow upon you my eternal gratitude. 

First up is handling application preferences: Implementing preferences is actually not too difficult, as the framework handles most of the heavy lifting for the developer, but there is a fair amount of configuration and a few lines of code required to get preference support up and running.

I've stripped out some of the code from the following examples, where the code removed is not directly related to handling preferences. If you'd like to view the code in its entirety, feel free to browse the app's GitHub repository.

The following steps are not presented in any particular order, but they are all mandatory.

Create a PreferenceFragment 

Since the Honeycomb release of Android, the recommended mechanism for handling preferences has been to use a Fragment rather than an Activity. Far be it from me to go against the Android teams sage advice, so I've used a Fragment in the Beacon Scanner app. The Fragment is responsible for loading up our preference definitions from the XML file we'll create in the next step, as you'll see from the code copied below:

package net.jmodwyer.beacon.beaconPoC;

import net.jmodwyer.ibeacon.ibeaconPoC.R;
import android.os.Bundle;
import android.preference.PreferenceFragment;

public class BeaconPoCPreferencesFragment extends PreferenceFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);
    }

}

Create an XML Preferences file

We'll need to create a file to hold your preference definitions. This file should live in our applications \res\xml folder, and in this example I've called the file preferences.xml, which you'll see is referenced in the PreferenceFragment implementation shown in the previous step. Here's the contents of the file for the Beacon Scanner & Logger:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
    
    <PreferenceCategory android:title="Beacon Properties to capture:" >

        <CheckBoxPreference
            android:defaultValue="true"
            android:key="index"
            android:summary="Log a count of beacon pings detected so far"
            android:title="Row Number" />        
        
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="uuid"
            android:summary="Log the UUID"
            android:title="UUID" />
                
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="majorMinor"
            android:summary="Log the Major and Minor values"
            android:title="Major Minor" />
        
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="rssi"
            android:summary="Log the RSSI value"
            android:title="RSSI" />
        
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="proximity"
            android:summary="Log the Proximity value"
            android:title="Proximity" />
        
        <CheckBoxPreference
            android:defaultValue="true"
            android:key="power"
            android:summary="Log the Power value"
            android:title="Power" />
                                                                        
        <CheckBoxPreference
            android:defaultValue="false"
            android:key="timestamp"
            android:summary="Log a Timestamp every time a beacon is detected"
            android:title="Timestamp" />
                                        
    </PreferenceCategory>

</PreferenceScreen>

Create an Activity so we can interact with our Preferences 

We'll need to provide an Activity that can be invoked when the user selects the Preferences option within the app. This Activity is responsible for invoking the PreferenceFragment we created earlier. Here's the code:

package net.jmodwyer.beacon.beaconPoC;

import android.app.Activity;
import android.os.Bundle;

public class AppPreferenceActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
  getFragmentManager().beginTransaction().replace(android.R.id.content,
               new BeaconPoCPreferencesFragment()).commit();
}

}


Add the Activity to our AndroidManifest.XML file.

Every Activity needs an entry in AndroidManifest, and this is ours:

        <activity
            android:name="net.jmodwyer.beacon.beaconPoC.AppPreferenceActivity"
            android:label="@string/app_name" >
            <intent-filter>
<action android:name="net.jmodwyer.ibeacon.ibeaconPoC.AppPreferenceActivity" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

Create a \res\menu\main_activity_actions.xml file

We need to create an xml file to define the options we'll display on our action bar menu.

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/Settings"
          android:title="@string/Settings"
          android:showAsAction="never"/>

</menu>

Modify \res\values\strings.xml

We defined a string called "Settings" in the main_activity_actions.xml file, so we now need to provide a definition for this in our application's strings.xml file.

<resources>

    <string name="Settings">Settings</string>

</resources>

Update our main Activity class

We need to make a number of changes to our main Activity class that will enable preference functionality within the app. For the sake of readability I've removed code that isn't related to the handling of preferences.

First we add code to our onCreate() method to load up the default values from our preferences file:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);

    }

Then we ensure the options menu, which is home to our Preferences option, is displayed when our main Activity is invoked:

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_activity_actions, menu);
        return super.onCreateOptionsMenu(menu);
    }

We'll need to override the onOptionsItemSelected(MenuItem) method so we can handle the user selecting the "Settings" option, which invokes our Preferences, from the action bar.

    // Handle the user selecting "Settings" from the action bar.
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
    case R.id.Settings:
        // Show settings
    Intent api = new Intent(this, AppPreferenceActivity.class);
        startActivityForResult(api, 0);
        return true;        
    default:
        return super.onOptionsItemSelected(item);
}
    }

Those are the only modifications required to load and support modification of preferences, but we obviously want to use the values store in these preferences within the application. Here's a section of the app's startScanning method, which reads preference values and stores them in Activity scoped variables for use in a subsequent method (note the use of constants for preference keys,  which are declared elsewhere in the Activity class):

    private void startScanning(Button scanButton) {

        // Get current values for logging preferences
SharedPreferences sharedPrefs =   PreferenceManager.getDefaultSharedPreferences(this);
HashMap <String, Object> prefs = new HashMap<String, Object>();
prefs.putAll(sharedPrefs.getAll());
   
index = (Boolean)prefs.get(PREFERENCE_INDEX);
uuid = (Boolean)prefs.get(PREFERENCE_UUID);
majorMinor = (Boolean)prefs.get(PREFERENCE_MAJORMINOR);
rssi = (Boolean)prefs.get(PREFERENCE_RSSI); 
proximity = (Boolean)prefs.get(PREFERENCE_PROXIMITY);
power = (Boolean)prefs.get(PREFERENCE_POWER);
timestamp = (Boolean)prefs.get(PREFERENCE_TIMESTAMP);
    }


...And we're done. If we follow the above steps we should now have an application in which we can display, modify and retrieve preferences. If you're still with me then thanks for your time, I hope this has helped you, and I'd love to have your feedback.

Version 1.3 of Beacon Scanner & Logger Supports Scanning in Background

Version 1.3 of Beacon Scanner and Logger has been released to Google Play. The new version allows the app to continue scanning when in background mode, but not while the phone is locked or has automatically entered sleep mode. I'm investigating the best way of implementing scanning while locked for a subsequent version of the app.

As usual, the app is available to download for free, and source code is available on GitHub.

Reviews and comments are welcome, and if there's a feature you'd like to see then please let me know.

Wednesday, 6 August 2014

Version 1.2 of Beacon Scanner & Logger (free) Released

Version 1.2 of Beacon Scanner & Logger (free) (formerly iBeacon Scanner (free)) has been released to Google Play.

This version of the app adds support for detecting and logging AltBeacons, and now uses the background power save feature of the Radius Networks Android Beacon Library SDK.

The app was published at 12:00 UK time, and will doubtless take a few hours to percolate through the Google Play App store.

Tuesday, 5 August 2014

Beacon Scanner and Logger App Now Uses AltBeacon Library from Radius Networks

I've updated the Beacon Scanner app so that it now uses the AltBeacon library from Radius Networks and removed any references to the iBeacon specific library previously used.

The app itself is currently still iBeacon specific, but AltBeacon support (and hopefully Gimbal Series 10 support) will be added shortly. Update - here's a section of one of the output files generated by the app that shows both an AltBeacon (actually a virtual AltBeacon) and an iBeacon being detected:

42 UUID: 00000000-0000-0000-0000-000000000000 Maj. Mnr.: 1-1 RSSI: -68 Proximity: Near Power: -59
43 UUID: 52414449-5553-4e45-5457-4f524b53434f Maj. Mnr.: 0-0 RSSI: -54 Proximity: Immediate Power: -59
44 UUID: 52414449-5553-4e45-5457-4f524b53434f Maj. Mnr.: 0-0 RSSI: -44 Proximity: Immediate Power: -59
45 UUID: 00000000-0000-0000-0000-000000000000 Maj. Mnr.: 1-1 RSSI: -70 Proximity: Near Power: -59
46 UUID: 52414449-5553-4e45-5457-4f524b53434f Maj. Mnr.: 0-0 RSSI: -42 Proximity: Immediate Power: -59
47 UUID: 52414449-5553-4e45-5457-4f524b53434f Maj. Mnr.: 0-0 RSSI: -52 Proximity: Immediate Power: -59
48 UUID: 00000000-0000-0000-0000-000000000000 Maj. Mnr.: 1-1 RSSI: -73 Proximity: Near Power: -59
49 UUID: 00000000-0000-0000-0000-000000000000 Maj. Mnr.: 1-1 RSSI: -55 Proximity: Near Power: -59
50 UUID: 52414449-5553-4e45-5457-4f524b53434f Maj. Mnr.: 0-0 RSSI: -55 Proximity: Immediate Power: -59

Entries showing the UUID constructed entirely of zeroes correspond to the AltBeacon.

Support for the Gimbal device is next on the list, though judging by this question on Stack Overflow from David G Young, that could be tricky.

Source code is available now on github, as is an apt file; note the repository name has changed to remove reference to "iBeacon". Some refactoring is needed, but I wanted to share the work in progress version in case it proves useful to anyone now.

I'll update the app on Google Play once I've tidied up the code, I'm planning to add background scanning support too but this may have to wait for a subsequent release.