You can subscribe also in background to receive Intent instead of MessageListener notifications. The background scanning is low-power scanning so the latency can be very long (even minutes to detect beacon). Scan is performed on screen-on event or when other app requests it. So you receive results from other apps scans.
You can create GoogleApiClient using application context instead of activity context. Call this i.e. from a broadcast receiver reacting to BOOT_COMPLETED broadcast.
GoogleApiClient client = new GoogleApiClient.Builder(appContext)
.addApi(Nearby.MESSAGES_API, new MessagesOptions.Builder()
.setPermissions(NearbyPermissions.BLE)
.build())
.build();
client.connect();
Once the client is connected (the onConnected method of ConnectionCallbacks) you can subscribe using PendingIntent and create Broadcast receiver that handles the intent.
In the broadcast receiver, you can handle intent using the Nearby.Messages.handleIntent method which is using same MessageListener as foreground scanning.
One of the problems with this approach are permissions to access Nearby. To allow user to approve access to Nearby you need UI. My solution was to wait with background scanning until user first time opens the app and accept the permissions. Once accepted you can subscribe in background.