Back to project page beaconbrowser.
The source code is released under:
MIT License
If you think the Android project beaconbrowser listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package org.waded.beaconbrowser; /* w ww . j a v a2 s .c o m*/ import android.app.Activity; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; import android.view.View; import android.webkit.WebChromeClient; import android.webkit.WebSettings; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; import com.google.common.collect.Ordering; import com.radiusnetworks.ibeacon.IBeacon; import com.radiusnetworks.ibeacon.IBeaconConsumer; import com.radiusnetworks.ibeacon.IBeaconManager; import com.radiusnetworks.ibeacon.RangeNotifier; import com.radiusnetworks.ibeacon.Region; import java.util.Collection; import java.util.List; public class BrowseActivity extends Activity implements IBeaconConsumer { private static final String TAG = BrowseActivity.class.getName(); private IBeaconManager iBeaconManager = IBeaconManager.getInstanceForApplication(this); private List<Entry> entryCache; private String currentEntryId; // Wildcard uuid, major, and minor to be notified of range of all of them private static final Region region = new Region(TAG, null, null, null); Ordering<IBeacon> byDistance = new Ordering<IBeacon>() { public int compare(IBeacon l, IBeacon r) { // accuracy means distance, but accurate it is not return Double.compare(l.getAccuracy(), r.getAccuracy()); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Bind for beacon ranging notifications. We won't start just yet to // avoid interfering with wifi, which we need to get the beacon info, // and later to load content. iBeaconManager.bind(this); // Start beacon sync startBeaconSync(); // Set up layout, particularly the webview setContentView(R.layout.activity_browse); WebView webView = (WebView) findViewById(R.id.webView); webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); webView.setWebChromeClient(new WebChromeClient()); webView.setWebViewClient(new WebViewClient() { public void onPageFinished(WebView view, String url) { startRanging(); } public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { startRanging(); } }); WebSettings settings = webView.getSettings(); settings.setJavaScriptEnabled(true); settings.setMediaPlaybackRequiresUserGesture(false); settings.setUserAgentString(TAG); } @Override protected void onPause() { stopRanging(); super.onPause(); } @Override protected void onResume() { startRanging(); super.onResume(); } @Override protected void onDestroy() { stopRanging(); iBeaconManager.unBind(this); super.onDestroy(); } private void startBeaconSync() { Log.i(TAG, "Starting refresh of entries"); BeaconSyncTask task = new BeaconSyncTask() { @Override public void onPostExecute(List<Entry> result) { entryCache = result; Log.i(TAG, "Refreshed " + entryCache.size() + " entries."); // OK to start now, we got the entryCache updated. startRanging(); } }; // We can make the WordPress site feed URL configurable later task.execute("http://waded-dci.azurewebsites.net/feed/atom"); } /** * Navigate the webview to the @param entry's link with debouncing on the entry's id, * since this will be called often by ranging notifications. */ public void startLoadUrlForEntry(final Entry entry) { if (!entry.id.equals(currentEntryId)) { stopRanging(); currentEntryId = entry.id; runOnUiThread(new Runnable() { @Override public void run() { Log.i(TAG, "Switching to new entry " + currentEntryId); WebView webView = (WebView) findViewById(R.id.webView); webView.loadUrl(entry.link); } }); } else { Log.i(TAG, "We're already at " + currentEntryId); } } /** * @return only an entry from entryCache that fully matches the given @param beacon. * Quite unforgiving for now. Returns null if no match. */ private Entry getBestEntry(IBeacon beacon) { for (Entry e : entryCache) { if (beacon.getProximityUuid().equals(e.beacon.uuid) && beacon.getMajor() == e.beacon.major && beacon.getMinor() == e.beacon.minor) { return e; } } return null; } @Override public void onIBeaconServiceConnect() { iBeaconManager.setRangeNotifier(new RangeNotifier() { @Override public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) { if (iBeacons.size() > 0) { if (entryCache != null) { IBeacon nearestBeacon = byDistance.min(iBeacons); Entry bestEntry = getBestEntry(nearestBeacon); if (bestEntry != null) startLoadUrlForEntry(bestEntry); } } } }); } /** * See https://code.google.com/p/android/issues/detail?id=41631 before considering * calling this. */ private void startRanging() { // We do not start if the entryCache is not established because there's // simply no reason to do so; we'll only interfere with getting it. // TODO: when we actually persist entryCache we'll want something more sensitive. if (entryCache == null) return; try { iBeaconManager.startRangingBeaconsInRegion(region); } catch (RemoteException e) { Log.e(TAG, "startRanging: " + e.getLocalizedMessage()); } } private void stopRanging() { try { iBeaconManager.stopRangingBeaconsInRegion(region); } catch (RemoteException e) { Log.e(TAG, "stopRanging: " + e.getLocalizedMessage()); } } }