diff --git a/android-uribeacon/uribeacon-sample/src/main/java/org/uribeacon/sample/SwipeRefreshLayout.java b/android-uribeacon/uribeacon-sample/src/main/java/org/uribeacon/sample/SwipeRefreshLayout.java new file mode 100644 index 0000000..a2a23bd --- /dev/null +++ b/android-uribeacon/uribeacon-sample/src/main/java/org/uribeacon/sample/SwipeRefreshLayout.java @@ -0,0 +1,30 @@ +package org.uribeacon.sample; + + + import android.content.Context; + import android.util.AttributeSet; + import android.widget.ListView; + +/** + * Subclass of {@link android.support.v4.widget.SwipeRefreshLayout} that supports containing a + * ViewGroup whose first child is a ListView. The ViewGroup can contain other views. + * + */ +public class SwipeRefreshLayout extends android.support.v4.widget.SwipeRefreshLayout { + + public SwipeRefreshLayout(Context context) { + super(context); + } + + public SwipeRefreshLayout(Context context, AttributeSet attributeSet) { + super(context, attributeSet); + } + + @Override public boolean canChildScrollUp() { + // The real child maps cares about is the list, so check if that can scroll. + ListView target = (ListView) findViewById(android.R.id.list); + return target.getChildCount() > 0 + && (target.getFirstVisiblePosition() > 0 + || target.getChildAt(0).getTop() < target.getPaddingTop()); + } +} diff --git a/android-uribeacon/uribeacon-sample/src/main/java/org/uribeacon/sample/UriBeaconScanActivity.java b/android-uribeacon/uribeacon-sample/src/main/java/org/uribeacon/sample/UriBeaconScanActivity.java index 06b3f75..29a711e 100644 --- a/android-uribeacon/uribeacon-sample/src/main/java/org/uribeacon/sample/UriBeaconScanActivity.java +++ b/android-uribeacon/uribeacon-sample/src/main/java/org/uribeacon/sample/UriBeaconScanActivity.java @@ -33,8 +33,9 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.ViewTreeObserver; +import android.view.Window; import android.widget.ListView; +import android.widget.TextView; import android.widget.Toast; import org.uribeacon.beacon.UriBeacon; @@ -65,7 +66,8 @@ public class UriBeaconScanActivity extends ListActivity implements SwipeRefreshL private DeviceListAdapter mLeDeviceListAdapter; private BluetoothAdapter mBluetoothAdapter; private boolean mIsScanRunning; - private SwipeRefreshLayout mSwipeLayout; + private SwipeRefreshLayout mSwipeWidget; + private boolean mIsConfig; private Parcelable[] mScanFilterUuids; // Run when the SCAN_TIME_MILLIS has elapsed. @@ -99,31 +101,39 @@ private boolean leScanMatches(ScanRecord scanRecord) { @SuppressWarnings("deprecation") private void scanLeDevice(final boolean enable) { if (mIsScanRunning != enable) { + TextView view = (TextView) findViewById(android.R.id.empty); mIsScanRunning = enable; + setProgressBarIndeterminateVisibility(enable); if (enable) { + view.setText(mIsConfig ? R.string.empty_config_start : R.string.empty_scan_start); // Stops scanning after the predefined scan time has elapsed. mHandler.postDelayed(mScanTimeout, SCAN_TIME_MILLIS); mLeDeviceListAdapter.clear(); - mSwipeLayout.setRefreshing(true); mBluetoothAdapter.startLeScan(mLeScanCallback); } else { // Cancel the scan timeout callback if still active or else it may fire later. mHandler.removeCallbacks(mScanTimeout); - mSwipeLayout.setRefreshing(false); mBluetoothAdapter.stopLeScan(mLeScanCallback); + view.setText(mIsConfig ? R.string.empty_config_end : R.string.empty_scan_end); } // update the refresh/stop refresh menu invalidateOptionsMenu(); } } + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.uribeacon_scan_layout); - mSwipeLayout = (SwipeRefreshLayout) findViewById(R.id.swiperefresh); - mSwipeLayout.setOnRefreshListener(this); + mSwipeWidget = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_widget); + mSwipeWidget.setOnRefreshListener(this); + + // Initializes list view adapter. + mLeDeviceListAdapter = new DeviceListAdapter(getLayoutInflater()); + setListAdapter(mLeDeviceListAdapter); // Use this check to determine whether BLE is supported on the device. Then you can // selectively disable BLE-related features. @@ -155,6 +165,7 @@ public boolean onCreateOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) { menu.findItem(R.id.menu_stop_refresh).setVisible(mIsScanRunning); menu.findItem(R.id.menu_refresh).setVisible(!mIsScanRunning); + menu.findItem(R.id.menu_config).setVisible(!mIsConfig); return super.onPrepareOptionsMenu(menu); } @@ -188,10 +199,8 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override protected void onListItemClick(ListView l, View v, int position, long id) { ScanResultAdapter.DeviceSighting sighting = mLeDeviceListAdapter.getItem(position); - List serviceUuids = sighting.scanResult.getScanRecord().getServiceUuids(); // Only open configuration activity if the selected devices advertises configuration. - if (serviceUuids.contains(ProtocolV1.CONFIG_SERVICE_UUID) || - serviceUuids.contains(ProtocolV2.CONFIG_SERVICE_UUID)) { + if (mIsConfig) { ConfigActivity.startConfigureActivity(this, sighting.scanResult); // On exit from configuration, return to the main scan screen. finish(); @@ -201,33 +210,24 @@ protected void onListItemClick(ListView l, View v, int position, long id) { @Override protected void onResume() { super.onResume(); - Parcelable configServices[] = getIntent().getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID); - // If we are invoked with EXTRA_UUID then we are configuration mode so set title. - if (configServices != null) { - getActionBar().setTitle(R.string.title_config); - } else { - getActionBar().setTitle(R.string.title_devices); - } + mIsConfig = configServices != null; - // Initializes list view adapter. - mLeDeviceListAdapter = new DeviceListAdapter(getLayoutInflater()); - setListAdapter(mLeDeviceListAdapter); + // If we are invoked with EXTRA_UUID then we are configuration mode so set title. + getActionBar().setTitle(mIsConfig ? R.string.title_config : R.string.title_devices); // Set the scan filter to be one of three filtering modes: all beacons, UriBeacons, // UriBeacons in config mode. final String keyUriBeacon = getString(R.string.pref_key_uribeacon); final SharedPreferences prefs = getDefaultSharedPreferences(this); boolean filterUriBeacon = prefs.getBoolean(keyUriBeacon, false); - if (configServices != null) { + if (mIsConfig) { mScanFilterUuids = configServices; } else if (filterUriBeacon) { mScanFilterUuids = new ParcelUuid[]{UriBeacon.URI_SERVICE_UUID}; } else { mScanFilterUuids = null; } - - // Start scanning scanLeDevice(true); } @@ -246,7 +246,6 @@ protected void onPause() { super.onPause(); // on Pause stop any scans that are running if not in background mode scanLeDevice(false); - } private int getTxPowerLevel(ScanResult scanResult) { @@ -264,6 +263,8 @@ private int getTxPowerLevel(ScanResult scanResult) { @Override public void onRefresh() { + // This obscures the contents, so keep in the action bar + mSwipeWidget.setRefreshing(false); scanLeDevice(true); } diff --git a/android-uribeacon/uribeacon-sample/src/main/res/layout-sw600dp/actionbar_indeterminate_progress.xml b/android-uribeacon/uribeacon-sample/src/main/res/layout-sw600dp/actionbar_indeterminate_progress.xml deleted file mode 100644 index 94c5a2d..0000000 --- a/android-uribeacon/uribeacon-sample/src/main/res/layout-sw600dp/actionbar_indeterminate_progress.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - diff --git a/android-uribeacon/uribeacon-sample/src/main/res/layout/actionbar_indeterminate_progress.xml b/android-uribeacon/uribeacon-sample/src/main/res/layout/actionbar_indeterminate_progress.xml deleted file mode 100644 index 94c5a2d..0000000 --- a/android-uribeacon/uribeacon-sample/src/main/res/layout/actionbar_indeterminate_progress.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - diff --git a/android-uribeacon/uribeacon-sample/src/main/res/layout/uribeacon_scan_layout.xml b/android-uribeacon/uribeacon-sample/src/main/res/layout/uribeacon_scan_layout.xml index 808016b..c072164 100644 --- a/android-uribeacon/uribeacon-sample/src/main/res/layout/uribeacon_scan_layout.xml +++ b/android-uribeacon/uribeacon-sample/src/main/res/layout/uribeacon_scan_layout.xml @@ -14,15 +14,31 @@ See the License for the specific language governing permissions and limitations under the License. --> - - + android:layout_height="match_parent"> - \ No newline at end of file + + + + + + + + \ No newline at end of file diff --git a/android-uribeacon/uribeacon-sample/src/main/res/values/dimens.xml b/android-uribeacon/uribeacon-sample/src/main/res/values/dimens.xml index 55c1e59..30c7751 100644 --- a/android-uribeacon/uribeacon-sample/src/main/res/values/dimens.xml +++ b/android-uribeacon/uribeacon-sample/src/main/res/values/dimens.xml @@ -2,6 +2,4 @@ 16dp - 16dp - diff --git a/android-uribeacon/uribeacon-sample/src/main/res/values/strings.xml b/android-uribeacon/uribeacon-sample/src/main/res/values/strings.xml index bb0f570..17fc012 100644 --- a/android-uribeacon/uribeacon-sample/src/main/res/values/strings.xml +++ b/android-uribeacon/uribeacon-sample/src/main/res/values/strings.xml @@ -21,6 +21,10 @@ Scan Config Bluetooth not supported. + Searching for devices + No devices found + Searching for configurable UriBeacons + No configurable UriBeacons found.\nVisit uribeacon.org Refresh diff --git a/android-uribeacon/uribeacon-sample/src/main/res/values/strings_config.xml b/android-uribeacon/uribeacon-sample/src/main/res/values/strings_config.xml index 43e7e04..1999060 100644 --- a/android-uribeacon/uribeacon-sample/src/main/res/values/strings_config.xml +++ b/android-uribeacon/uribeacon-sample/src/main/res/values/strings_config.xml @@ -1,7 +1,5 @@ - Beacon Configuration - Old value New value Write