Update BTAds sample to use a service for advertising

The BluetoothAdvertisements sample originally did BT advertising
in the main fragment, which meant (for memory leak reasons) it
would only advertise when the app was visible on the screen.
Now it uses a service, yay!

Change-Id: I08c860d228c857099b835b340dc21e8e265e80c5
diff --git a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/AndroidManifest.xml b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/AndroidManifest.xml
index 48084fc..cd2a65e 100644
--- a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/AndroidManifest.xml
+++ b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/AndroidManifest.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="UTF-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <!--
  Copyright 2013 The Android Open Source Project
 
@@ -17,23 +17,32 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.example.android.bluetoothadvertisements"
     android:versionCode="1"
-    android:versionName="1.0">
+    android:versionName="1.0" >
 
-    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-    <uses-permission android:name="android.permission.BLUETOOTH"/>
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
 
-    <application android:allowBackup="true"
-        android:label="@string/app_name"
+    <application
+        android:allowBackup="true"
         android:icon="@drawable/ic_launcher"
-        android:theme="@style/AppTheme">
-
-        <activity android:name=".MainActivity"
-                  android:label="@string/app_name">
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name=".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>
+
+        <!-- Service to handle BLE Advertising - Using a service allows advertising to continue
+             when the app is no longer on screen in a reliable manner.  -->
+        <service
+            android:name=".AdvertiserService"
+            android:enabled="true"
+            android:exported="false" >
+        </service>
     </application>
 
 </manifest>
diff --git a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/AdvertiserFragment.java b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/AdvertiserFragment.java
index f3645fc..c97b904 100644
--- a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/AdvertiserFragment.java
+++ b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/AdvertiserFragment.java
@@ -16,11 +16,11 @@
 
 package com.example.android.bluetoothadvertisements;
 
-import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.le.AdvertiseCallback;
-import android.bluetooth.le.AdvertiseData;
-import android.bluetooth.le.AdvertiseSettings;
-import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
 import android.view.LayoutInflater;
@@ -32,67 +32,121 @@
 /**
  * Allows user to start & stop Bluetooth LE Advertising of their device.
  */
-public class AdvertiserFragment extends Fragment {
+public class AdvertiserFragment extends Fragment implements View.OnClickListener {
 
-    private BluetoothAdapter mBluetoothAdapter;
-
-    private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
-
-    private AdvertiseCallback mAdvertiseCallback;
-
+    /**
+     * Lets user toggle BLE Advertising.
+     */
     private Switch mSwitch;
 
     /**
-     * Must be called after object creation by MainActivity.
-     *
-     * @param btAdapter the local BluetoothAdapter
+     * Listens for notifications that the {@code AdvertiserService} has failed to start advertising.
+     * This Receiver deals with Fragment UI elements and only needs to be active when the Fragment
+     * is on-screen, so it's defined and registered in code instead of the Manifest.
      */
-    public void setBluetoothAdapter(BluetoothAdapter btAdapter) {
-        this.mBluetoothAdapter = btAdapter;
-        mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
-    }
+    private BroadcastReceiver advertisingFailureReceiver;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        setRetainInstance(true);
+
+        advertisingFailureReceiver = new BroadcastReceiver() {
+
+            /**
+             * Receives Advertising error codes from {@code AdvertiserService} and displays error messages
+             * to the user. Sets the advertising toggle to 'false.'
+             */
+            @Override
+            public void onReceive(Context context, Intent intent) {
+
+                int errorCode = intent.getIntExtra(AdvertiserService.ADVERTISING_FAILED_EXTRA_CODE, -1);
+
+                mSwitch.setChecked(false);
+
+                String errorMessage = getString(R.string.start_error_prefix);
+                switch (errorCode) {
+                    case AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED:
+                        errorMessage += " " + getString(R.string.start_error_already_started);
+                        break;
+                    case AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE:
+                        errorMessage += " " + getString(R.string.start_error_too_large);
+                        break;
+                    case AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED:
+                        errorMessage += " " + getString(R.string.start_error_unsupported);
+                        break;
+                    case AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR:
+                        errorMessage += " " + getString(R.string.start_error_internal);
+                        break;
+                    case AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS:
+                        errorMessage += " " + getString(R.string.start_error_too_many);
+                        break;
+                    case AdvertiserService.ADVERTISING_TIMED_OUT:
+                        errorMessage = " " + getString(R.string.advertising_timedout);
+                        break;
+                    default:
+                        errorMessage += " " + getString(R.string.start_error_unknown);
+                }
+
+                Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_LONG).show();
+            }
+        };
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
-            Bundle savedInstanceState) {
+                             Bundle savedInstanceState) {
 
         View view = inflater.inflate(R.layout.fragment_advertiser, container, false);
 
         mSwitch = (Switch) view.findViewById(R.id.advertise_switch);
-        mSwitch.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                onSwitchClicked(v);
-            }
-        });
+        mSwitch.setOnClickListener(this);
 
         return view;
     }
 
+    /**
+     * When app comes on screen, check if BLE Advertisements are running, set switch accordingly,
+     * and register the Receiver to be notified if Advertising fails.
+     */
     @Override
-    public void onStop() {
-        super.onStop();
+    public void onResume() {
+        super.onResume();
 
-        if(mAdvertiseCallback != null){
-            stopAdvertising();
+        if (AdvertiserService.running) {
+            mSwitch.setChecked(true);
+        } else {
+            mSwitch.setChecked(false);
         }
+
+        IntentFilter failureFilter = new IntentFilter(AdvertiserService.ADVERTISING_FAILED);
+        getActivity().registerReceiver(advertisingFailureReceiver, failureFilter);
+
+    }
+
+    /**
+     * When app goes off screen, unregister the Advertising failure Receiver to stop memory leaks.
+     * (and because the app doesn't care if Advertising fails while the UI isn't active)
+     */
+    @Override
+    public void onPause() {
+        super.onPause();
+        getActivity().unregisterReceiver(advertisingFailureReceiver);
+    }
+
+    /**
+     * Returns Intent addressed to the {@code AdvertiserService} class.
+     */
+    private static Intent getServiceIntent(Context c) {
+        return new Intent(c, AdvertiserService.class);
     }
 
     /**
      * Called when switch is toggled - starts or stops advertising.
-     *
-     * @param view is the Switch View object
      */
-    public void onSwitchClicked(View view) {
-
+    @Override
+    public void onClick(View v) {
         // Is the toggle on?
-        boolean on = ((Switch) view).isChecked();
+        boolean on = ((Switch) v).isChecked();
 
         if (on) {
             startAdvertising();
@@ -102,105 +156,20 @@
     }
 
     /**
-     * Starts BLE Advertising.
+     * Starts BLE Advertising by starting {@code AdvertiserService}.
      */
     private void startAdvertising() {
-
-        mAdvertiseCallback = new SampleAdvertiseCallback();
-
-        if (mBluetoothLeAdvertiser != null) {
-            mBluetoothLeAdvertiser.startAdvertising(buildAdvertiseSettings(), buildAdvertiseData(),
-                    mAdvertiseCallback);
-        } else {
-            mSwitch.setChecked(false);
-            Toast.makeText(getActivity(), getString(R.string.bt_null), Toast.LENGTH_LONG).show();
-        }
+        Context c = getActivity();
+        c.startService(getServiceIntent(c));
     }
 
     /**
-     * Stops BLE Advertising.
+     * Stops BLE Advertising by stopping {@code AdvertiserService}.
      */
     private void stopAdvertising() {
-
-        if (mBluetoothLeAdvertiser != null) {
-
-            mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
-            mAdvertiseCallback = null;
-
-        } else {
-            mSwitch.setChecked(false);
-            Toast.makeText(getActivity(), getString(R.string.bt_null), Toast.LENGTH_LONG).show();
-        }
+        Context c = getActivity();
+        c.stopService(getServiceIntent(c));
+        mSwitch.setChecked(false);
     }
 
-    /**
-     * Returns an AdvertiseData object which includes the Service UUID and Device Name.
-     */
-    private AdvertiseData buildAdvertiseData() {
-
-        // Note: There is a strict limit of 31 Bytes on packets sent over BLE Advertisements.
-        // This includes everything put into AdvertiseData including UUIDs, device info, &
-        // arbitrary service or manufacturer data.
-        // Attempting to send packets over this limit will result in a failure with error code
-        // AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE. Catch this error in the
-        // onStartFailure() method of an AdvertiseCallback implementation.
-
-        AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
-        dataBuilder.addServiceUuid(Constants.Service_UUID);
-        dataBuilder.setIncludeDeviceName(true);
-
-        return dataBuilder.build();
-    }
-
-    /**
-     * Returns an AdvertiseSettings object set to use low power (to help preserve battery life).
-     */
-    private AdvertiseSettings buildAdvertiseSettings() {
-        AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
-        settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
-
-        return settingsBuilder.build();
-    }
-
-    /**
-     * Custom callback after Advertising succeeds or fails to start.
-     */
-    private class SampleAdvertiseCallback extends AdvertiseCallback {
-
-        @Override
-        public void onStartFailure(int errorCode) {
-            super.onStartFailure(errorCode);
-
-            mSwitch.setChecked(false);
-
-            String errorMessage = getString(R.string.start_error_prefix);
-            switch (errorCode) {
-                case AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED:
-                    errorMessage += " " + getString(R.string.start_error_already_started);
-                    break;
-                case AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE:
-                    errorMessage += " " + getString(R.string.start_error_too_large);
-                    break;
-                case AdvertiseCallback.ADVERTISE_FAILED_FEATURE_UNSUPPORTED:
-                    errorMessage += " " + getString(R.string.start_error_unsupported);
-                    break;
-                case AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR:
-                    errorMessage += " " + getString(R.string.start_error_internal);
-                    break;
-                case AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS:
-                    errorMessage += " " + getString(R.string.start_error_too_many);
-                    break;
-            }
-
-            Toast.makeText(getActivity(), errorMessage, Toast.LENGTH_LONG).show();
-
-        }
-
-        @Override
-        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
-            super.onStartSuccess(settingsInEffect);
-            // Don't need to do anything here, advertising successfully started.
-        }
-    }
-
-}
+}
\ No newline at end of file
diff --git a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/AdvertiserService.java b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/AdvertiserService.java
new file mode 100644
index 0000000..0cc3ff0
--- /dev/null
+++ b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/AdvertiserService.java
@@ -0,0 +1,223 @@
+package com.example.android.bluetoothadvertisements;
+
+import android.app.Service;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Manages BLE Advertising independent of the main app.
+ * If the app goes off screen (or gets killed completely) advertising can continue because this
+ * Service is maintaining the necessary Callback in memory.
+ */
+public class AdvertiserService extends Service {
+
+    private static final String TAG = AdvertiserService.class.getSimpleName();
+
+    /**
+     * A global variable to let AdvertiserFragment check if the Service is running without needing
+     * to start or bind to it.
+     * This is the best practice method as defined here:
+     * https://groups.google.com/forum/#!topic/android-developers/jEvXMWgbgzE
+     */
+    public static boolean running = false;
+
+    public static final String ADVERTISING_FAILED =
+            "com.example.android.bluetoothadvertisements.advertising_failed";
+
+    public static final String ADVERTISING_FAILED_EXTRA_CODE = "failureCode";
+
+    public static final int ADVERTISING_TIMED_OUT = 6;
+
+    private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
+
+    private AdvertiseCallback mAdvertiseCallback;
+
+    private Handler mHandler;
+
+    private Runnable timeoutRunnable;
+
+    /**
+     * Length of time to allow advertising before automatically shutting off. (10 minutes)
+     */
+    private long TIMEOUT = TimeUnit.MILLISECONDS.convert(10, TimeUnit.MINUTES);
+
+    @Override
+    public void onCreate() {
+        running = true;
+        initialize();
+        startAdvertising();
+        setTimeout();
+        super.onCreate();
+    }
+
+    @Override
+    public void onDestroy() {
+        /**
+         * Note that onDestroy is not guaranteed to be called quickly or at all. Services exist at
+         * the whim of the system, and onDestroy can be delayed or skipped entirely if memory need
+         * is critical.
+         */
+        running = false;
+        stopAdvertising();
+        mHandler.removeCallbacks(timeoutRunnable);
+        super.onDestroy();
+    }
+
+    /**
+     * Required for extending service, but this will be a Started Service only, so no need for
+     * binding.
+     */
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    /**
+     * Get references to system Bluetooth objects if we don't have them already.
+     */
+    private void initialize() {
+        if (mBluetoothLeAdvertiser == null) {
+            BluetoothManager mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+            if (mBluetoothManager != null) {
+                BluetoothAdapter mBluetoothAdapter = mBluetoothManager.getAdapter();
+                if (mBluetoothAdapter != null) {
+                    mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
+                } else {
+                    Toast.makeText(this, getString(R.string.bt_null), Toast.LENGTH_LONG).show();
+                }
+            } else {
+                Toast.makeText(this, getString(R.string.bt_null), Toast.LENGTH_LONG).show();
+            }
+        }
+
+    }
+
+    /**
+     * Starts a delayed Runnable that will cause the BLE Advertising to timeout and stop after a
+     * set amount of time.
+     */
+    private void setTimeout(){
+        mHandler = new Handler();
+        timeoutRunnable = new Runnable() {
+            @Override
+            public void run() {
+                Log.d(TAG, "AdvertiserService has reached timeout of "+TIMEOUT+" milliseconds, stopping advertising.");
+                sendFailureIntent(ADVERTISING_TIMED_OUT);
+                stopSelf();
+            }
+        };
+        mHandler.postDelayed(timeoutRunnable, TIMEOUT);
+    }
+
+    /**
+     * Starts BLE Advertising.
+     */
+    private void startAdvertising() {
+        Log.d(TAG, "Service: Starting Advertising");
+
+        if (mAdvertiseCallback == null) {
+            AdvertiseSettings settings = buildAdvertiseSettings();
+            AdvertiseData data = buildAdvertiseData();
+            mAdvertiseCallback = new SampleAdvertiseCallback();
+
+            if (mBluetoothLeAdvertiser != null) {
+                mBluetoothLeAdvertiser.startAdvertising(settings, data,
+                        mAdvertiseCallback);
+            }
+        }
+    }
+
+    /**
+     * Stops BLE Advertising.
+     */
+    private void stopAdvertising() {
+        Log.d(TAG, "Service: Stopping Advertising");
+        if (mBluetoothLeAdvertiser != null) {
+            mBluetoothLeAdvertiser.stopAdvertising(mAdvertiseCallback);
+            mAdvertiseCallback = null;
+        }
+    }
+
+    /**
+     * Returns an AdvertiseData object which includes the Service UUID and Device Name.
+     */
+    private AdvertiseData buildAdvertiseData() {
+
+        /**
+         * Note: There is a strict limit of 31 Bytes on packets sent over BLE Advertisements.
+         *  This includes everything put into AdvertiseData including UUIDs, device info, &
+         *  arbitrary service or manufacturer data.
+         *  Attempting to send packets over this limit will result in a failure with error code
+         *  AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE. Catch this error in the
+         *  onStartFailure() method of an AdvertiseCallback implementation.
+         */
+
+        AdvertiseData.Builder dataBuilder = new AdvertiseData.Builder();
+        dataBuilder.addServiceUuid(Constants.Service_UUID);
+        dataBuilder.setIncludeDeviceName(true);
+
+        /* For example - this will cause advertising to fail (exceeds size limit) */
+        //String failureData = "asdghkajsghalkxcjhfa;sghtalksjcfhalskfjhasldkjfhdskf";
+        //dataBuilder.addServiceData(Constants.Service_UUID, failureData.getBytes());
+
+        return dataBuilder.build();
+    }
+
+    /**
+     * Returns an AdvertiseSettings object set to use low power (to help preserve battery life)
+     * and disable the built-in timeout since this code uses its own timeout runnable.
+     */
+    private AdvertiseSettings buildAdvertiseSettings() {
+        AdvertiseSettings.Builder settingsBuilder = new AdvertiseSettings.Builder();
+        settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
+        settingsBuilder.setTimeout(0);
+        return settingsBuilder.build();
+    }
+
+    /**
+     * Custom callback after Advertising succeeds or fails to start. Broadcasts the error code
+     * in an Intent to be picked up by AdvertiserFragment and stops this Service.
+     */
+    private class SampleAdvertiseCallback extends AdvertiseCallback {
+
+        @Override
+        public void onStartFailure(int errorCode) {
+            super.onStartFailure(errorCode);
+
+            Log.d(TAG, "Advertising failed");
+            sendFailureIntent(errorCode);
+            stopSelf();
+
+        }
+
+        @Override
+        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
+            super.onStartSuccess(settingsInEffect);
+            Log.d(TAG, "Advertising successfully started");
+        }
+    }
+
+    /**
+     * Builds and sends a broadcast intent indicating Advertising has failed. Includes the error
+     * code as an extra. This is intended to be picked up by the {@code AdvertiserFragment}.
+     */
+    private void sendFailureIntent(int errorCode){
+        Intent failureIntent = new Intent();
+        failureIntent.setAction(ADVERTISING_FAILED);
+        failureIntent.putExtra(ADVERTISING_FAILED_EXTRA_CODE, errorCode);
+        sendBroadcast(failureIntent);
+    }
+
+}
\ No newline at end of file
diff --git a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/MainActivity.java b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/MainActivity.java
index 871935d..7ea3891 100644
--- a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/MainActivity.java
+++ b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/MainActivity.java
@@ -39,7 +39,7 @@
         setContentView(R.layout.activity_main);
         setTitle(R.string.activity_main_title);
 
-        if (savedInstanceState == null ) {
+        if (savedInstanceState == null) {
 
             mBluetoothAdapter = ((BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE))
                     .getAdapter();
@@ -112,11 +112,11 @@
         FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
 
         ScannerFragment scannerFragment = new ScannerFragment();
+        // Fragments can't access system services directly, so pass it the BluetoothAdapter
         scannerFragment.setBluetoothAdapter(mBluetoothAdapter);
         transaction.replace(R.id.scanner_fragment_container, scannerFragment);
 
         AdvertiserFragment advertiserFragment = new AdvertiserFragment();
-        advertiserFragment.setBluetoothAdapter(mBluetoothAdapter);
         transaction.replace(R.id.advertiser_fragment_container, advertiserFragment);
 
         transaction.commit();
diff --git a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScanResultAdapter.java b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScanResultAdapter.java
index f3c141d..5a9b954 100644
--- a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScanResultAdapter.java
+++ b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScanResultAdapter.java
@@ -75,7 +75,11 @@
 
         ScanResult scanResult = mArrayList.get(position);
 
-        deviceNameView.setText(scanResult.getDevice().getName());
+        String name = scanResult.getDevice().getName();
+        if (name == null) {
+            name = mContext.getResources().getString(R.string.no_name);
+        }
+        deviceNameView.setText(name);
         deviceAddressView.setText(scanResult.getDevice().getAddress());
         lastSeenView.setText(getTimeSinceString(mContext, scanResult.getTimestampNanos()));
 
diff --git a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScannerFragment.java b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScannerFragment.java
index ebb1ad0..4f5c2aa 100644
--- a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScannerFragment.java
+++ b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/java/com/example/android/bluetoothadvertisements/ScannerFragment.java
@@ -83,7 +83,7 @@
         // We could get a LayoutInflater from the ApplicationContext but it messes with the
         // default theme, so generate it from getActivity() and pass it in separately.
         mAdapter = new ScanResultAdapter(getActivity().getApplicationContext(),
-                                                    LayoutInflater.from(getActivity()));
+                LayoutInflater.from(getActivity()));
         mHandler = new Handler();
 
     }
@@ -180,6 +180,7 @@
         List<ScanFilter> scanFilters = new ArrayList<>();
 
         ScanFilter.Builder builder = new ScanFilter.Builder();
+        // Comment out the below line to see all BLE devices around you
         builder.setServiceUuid(Constants.Service_UUID);
         scanFilters.add(builder.build());
 
diff --git a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/res/values/strings.xml b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/res/values/strings.xml
index 197178d..927f3b6 100644
--- a/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/res/values/strings.xml
+++ b/connectivity/bluetooth/BluetoothAdvertisements/Application/src/main/res/values/strings.xml
@@ -26,5 +26,8 @@
     <string name="seconds">seconds.</string>
     <string name="scan_start_toast">Scanning for</string>
     <string name="already_scanning">Scanning already started.</string>
+    <string name="no_name">(no name)</string>
+    <string name="start_error_unknown">unknown error</string>
+    <string name="advertising_timedout">Advertising stopped due to timeout.</string>
 
 </resources>
\ No newline at end of file