package io.trygvis.soilmoisture; import android.app.ActionBar; import android.app.ListActivity; import android.app.ProgressDialog; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.crashlytics.android.Crashlytics; import java.util.ArrayList; import java.util.List; import io.fabric.sdk.android.Fabric; import io.trygvis.android.LocalBinder; import io.trygvis.android.bt.BtActivitySupport; import static io.trygvis.soilmoisture.ExceptionHandler.EXCEPTION_HANDLER; import static io.trygvis.soilmoisture.SmDevicesManager.SmDeviceListener; import static java.lang.String.valueOf; public class MainActivity extends ListActivity { private final static String TAG = MainActivity.class.getSimpleName(); private static final long SCAN_PERIOD = 3 * 1000; private static final int REQUEST_ENABLE_BT = 1; private final BtActivitySupport btActivitySupport = new BtActivitySupport(this, REQUEST_ENABLE_BT); private final SmDeviceListener serviceListener = new MySmDeviceListener(); private final MainActivity context = this; private DeviceListAdapter deviceList; private ServiceConnection serviceConnection; private SmDevicesManager smDevicesManager; private ProgressDialog initializing; private boolean ready; @Override protected void onCreate(Bundle savedInstanceState) { Log.i(TAG, "onCreate"); Thread.setDefaultUncaughtExceptionHandler(EXCEPTION_HANDLER); super.onCreate(savedInstanceState); Fabric.with(this, new Crashlytics()); ActionBar actionBar = getActionBar(); if (actionBar != null) { actionBar.setTitle(R.string.title_devices); } if (!btActivitySupport.onCreate()) { finish(); return; } serviceConnection = new ServiceConnection() { @SuppressWarnings("unchecked") @Override public void onServiceConnected(ComponentName componentName, IBinder service) { Log.i(TAG, "onServiceConnected"); smDevicesManager = ((LocalBinder) service).getService(); registerReceiver(serviceListener, SmDeviceListener.INTENT_FILTER); } @Override public void onServiceDisconnected(ComponentName componentName) { Log.i(TAG, "onServiceDisconnected"); smDevicesManager = null; stopScan(); } }; bindService(new Intent(this, DefaultSmDevicesManager.class), serviceConnection, BIND_AUTO_CREATE); initializing = ProgressDialog. show(this, "Initializing", "Connecting to Bluetooth system.", true); } @Override protected void onDestroy() { Log.i(TAG, "onDestroy"); super.onDestroy(); if (serviceConnection != null) { unbindService(serviceConnection); } } @Override protected void onResume() { Log.i(TAG, "onResume"); super.onResume(); if (!btActivitySupport.enableBt()) { finish(); return; } registerReceiver(serviceListener, SmDeviceListener.INTENT_FILTER); } @Override protected void onPause() { Log.i(TAG, "onPause"); super.onPause(); stopScan(); unregisterReceiver(serviceListener); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { Log.i(TAG, "onActivityResult"); if (!btActivitySupport.onActivityResult(requestCode, resultCode, data)) { finish(); } super.onActivityResult(requestCode, resultCode, data); } @Override public boolean onCreateOptionsMenu(Menu menu) { Log.i(TAG, "onCreateOptionsMenu"); // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); if (ready) { if (!smDevicesManager.isScanning()) { menu.findItem(R.id.menu_stop).setVisible(false); menu.findItem(R.id.menu_scan).setVisible(true); menu.findItem(R.id.menu_refresh).setActionView(null); } else { menu.findItem(R.id.menu_stop).setVisible(true); menu.findItem(R.id.menu_scan).setVisible(false); menu.findItem(R.id.menu_refresh).setActionView(R.layout.actionbar_indeterminate_progress); } } else { menu.findItem(R.id.menu_stop).setVisible(false); menu.findItem(R.id.menu_scan).setVisible(true); menu.findItem(R.id.menu_refresh).setActionView(null); } return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { Log.i(TAG, "onOptionsItemSelected"); switch (item.getItemId()) { case R.id.menu_scan: startScan(); break; case R.id.menu_stop: stopScan(); break; } return super.onOptionsItemSelected(item); } private void startScan() { smDevicesManager.startScanning(SCAN_PERIOD); } private void stopScan() { if (smDevicesManager != null) { smDevicesManager.stopScanning(); } } @Override protected void onListItemClick(ListView l, View v, int position, long id) { stopScan(); // SmDevice state = smDevicesManager.getDevices(SmDevice.deviceComparator).get(position); } // ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- static class DeviceListItem { final TextView deviceName; final TextView deviceAddress; final TextView rssi; final ProgressBar spinner; final Button connect; DeviceListItem(View view) { this.deviceName = (TextView) view.findViewById(R.id.device_name); this.deviceAddress = (TextView) view.findViewById(R.id.device_address); this.rssi = (TextView) view.findViewById(R.id.device_rssi); this.spinner = (ProgressBar) view.findViewById(R.id.device_spinner); this.connect = (Button) view.findViewById(R.id.button_connect); } } private class DeviceListAdapter extends BaseAdapter { private List devices = new ArrayList<>(); private LayoutInflater inflater = MainActivity.this.getLayoutInflater(); @Override public int getCount() { return devices.size(); } @Override public SmDevice getItem(int i) { return devices.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { DeviceListItem item; if (view == null) { view = inflater.inflate(R.layout.listitem_device, null); item = new DeviceListItem(view); view.setTag(item); view.setClickable(false); } else { item = (DeviceListItem) view.getTag(); } SmDevice smDevice = getItem(i); if (smDevice.getName() != null) { item.deviceName.setText(smDevice.getName()); } else { item.deviceName.setText(R.string.unknown_device); } item.deviceAddress.setText(smDevice.getBtDevice().getAddress()); item.rssi.setText(getText(R.string.rssi) + ": " + (smDevice.getBtDevice().getRssi() != 0 ? valueOf(smDevice.getBtDevice().getRssi()) : getText(R.string.unknown))); boolean useful = smDevice.isUseful(); item.spinner.setVisibility(useful ? View.GONE : View.VISIBLE); item.connect.setVisibility(useful ? View.VISIBLE : View.GONE); view.setClickable(useful); return view; } } private class MySmDeviceListener extends SmDeviceListener { @Override public void onReady(boolean ok) { if (!ok) { Toast.makeText(context, "Could not initialize services.", Toast.LENGTH_SHORT). show(); finish(); } else { ready = true; deviceList = new DeviceListAdapter(); setListAdapter(deviceList); deviceList.notifyDataSetChanged(); startScan(); initializing.dismiss(); } } @Override public void onScanStarted() { invalidateOptionsMenu(); } @Override public void onScanStopped() { invalidateOptionsMenu(); } @Override public void onNewDevice(String address) { SmDevice device = smDevicesManager.getDevice(address); deviceList.devices.add(device); deviceList.notifyDataSetInvalidated(); Log.i(TAG, "deviceList.devices.size() = " + deviceList.devices.size()); } } }