From 7a7d015f8a68f5e0d06fe6e3d9422d5f418f653d Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 30 Nov 2014 23:55:54 +0100 Subject: o Initial import of Fiken Status Display app. --- .../java/no/topi/fiken/display/MainActivity.java | 335 +++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 app/src/main/java/no/topi/fiken/display/MainActivity.java (limited to 'app/src/main/java/no/topi/fiken/display/MainActivity.java') diff --git a/app/src/main/java/no/topi/fiken/display/MainActivity.java b/app/src/main/java/no/topi/fiken/display/MainActivity.java new file mode 100644 index 0000000..d9dc073 --- /dev/null +++ b/app/src/main/java/no/topi/fiken/display/MainActivity.java @@ -0,0 +1,335 @@ +package no.topi.fiken.display; + +import android.app.ActionBar; +import android.app.Activity; +import android.app.ListActivity; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.os.Handler; +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.ListView; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.List; + +import static java.lang.String.valueOf; +import static no.topi.fiken.display.DisplayService.IntentAction; +import static no.topi.fiken.display.DisplayService.IntentExtra; +import static no.topi.fiken.display.ExceptionHandler.EXCEPTION_HANDLER; + +public class MainActivity extends ListActivity { + private final static String TAG = MainActivity.class.getSimpleName(); + + // Stops scanning after 10 seconds. + private static final long SCAN_PERIOD = 3 * 1000; + + private static final int REQUEST_ENABLE_BT = 1; + + private DisplayListAdapter displayList; + private Handler handler; + private BluetoothAdapter mBluetoothAdapter; + private boolean mScanning; + private DisplayService displayService; + private String deviceToShow; + + @Override + protected void onCreate(Bundle savedInstanceState) { + Log.i(TAG, "onCreate"); + Thread.setDefaultUncaughtExceptionHandler(EXCEPTION_HANDLER); + super.onCreate(savedInstanceState); + + ActionBar actionBar = getActionBar(); + if (actionBar != null) { + actionBar.setTitle(R.string.title_devices); + } + handler = new Handler(); + + // Use this check to determine whether BLE is supported on the device. Then you can + // selectively disable BLE-related features. + if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { + Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); + finish(); + } + + // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to + // BluetoothAdapter through BluetoothManager. + final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); + mBluetoothAdapter = bluetoothManager.getAdapter(); + + // Checks if Bluetooth is supported on the device. + if (mBluetoothAdapter == null) { + Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show(); + finish(); + } + + ServiceConnection serviceConnection = new ServiceConnection() { + + @Override + public void onServiceConnected(ComponentName componentName, IBinder service) { + displayService = ((DisplayService.LocalBinder) service).getService(); + if (!displayService.initialize()) { + finish(); + } + + startScan(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + stopScan(); + displayService = null; + } + }; + + Intent displayServiceIntent = new Intent(this, DefaultDisplayService.class); + bindService(displayServiceIntent, serviceConnection, BIND_AUTO_CREATE); + } + + @Override + protected void onResume() { + Log.i(TAG, "onResume"); + + super.onResume(); + + // Ensures Bluetooth is enabled on the device. If Bluetooth is not currently enabled, + // fire an intent to display a dialog asking the user to grant permission to enable it. + if (!mBluetoothAdapter.isEnabled()) { + Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); + startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); + } + + registerReceiver(displayServiceBroadcastReceiver, IntentAction.ALL_FILTER); + } + + @Override + protected void onPause() { + Log.i(TAG, "onPause"); + + super.onPause(); + stopScan(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + Log.i(TAG, "onActivityResult"); + + // User chose not to enable Bluetooth. + if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_CANCELED) { + finish(); + return; + } + + 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 (!mScanning) { + 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); + } + 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() { + displayList = new DisplayListAdapter(); + setListAdapter(displayList); + + displayService.startScan(); + + // Stops scanning after a pre-defined scan period. + handler.postDelayed(new Runnable() { + @Override + public void run() { + displayService.stopScan(); + invalidateOptionsMenu(); + } + }, SCAN_PERIOD); + } + + private void stopScan() { + if (displayService != null) { + displayService.stopScan(); + } + } + + @Override + protected void onListItemClick(ListView l, View v, int position, long id) { + stopScan(); + + DisplayService.DeviceInfo state = displayList.getDevice(position); + + if (!displayService.connect(state.address)) { + Toast.makeText(this, "Could not connect to " + state.address, Toast.LENGTH_SHORT).show(); + } else { + deviceToShow = state.address; + } + } + + private final BroadcastReceiver displayServiceBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(final Context context, final Intent intent) { + runOnUiThread(new Runnable() { + @Override + public void run() { + IntentAction action = IntentAction.valueOf(intent); + + String deviceAddress = intent.getStringExtra(IntentExtra.DEVICE_ADDRESS.name()); + + if (action == IntentAction.DEVICE_UPDATE && deviceAddress != null) { + DisplayService.DeviceInfo device = displayList.getDevice(deviceAddress, true); + + device.update(intent); + + if (intent.hasExtra(IntentExtra.CONNECTED.name())) { + boolean connected = intent.getBooleanExtra(IntentExtra.CONNECTED.name(), false); + + if (connected) { + if (deviceToShow != null && deviceToShow.equals(device.address)) { + Log.i(TAG, "connected to " + deviceToShow); + final Intent intent = new Intent(context, DisplayControlActivity.class); + intent.putExtra(IntentExtra.DEVICE_ADDRESS.name(), device.address); + intent.putExtra(IntentExtra.DEVICE_NAME.name(), device.name); + startActivity(intent); + } + } + } + displayList.notifyDataSetChanged(); + } + + if (intent.hasExtra(IntentExtra.SCANNING.name())) { + mScanning = intent.getBooleanExtra(IntentExtra.SCANNING.name(), false); + invalidateOptionsMenu(); + } + } + }); + } + }; + + static class ViewHolder { + final TextView deviceName; + final TextView deviceAddress; + final TextView rssi; + final TextView isDisplay; + + ViewHolder(TextView deviceName, TextView deviceAddress, TextView rssi, TextView isDisplay) { + this.deviceName = deviceName; + this.deviceAddress = deviceAddress; + this.rssi = rssi; + this.isDisplay = isDisplay; + } + } + + private class DisplayListAdapter extends BaseAdapter { + private List devices = new ArrayList(); + private LayoutInflater inflater = MainActivity.this.getLayoutInflater(); + + public DisplayService.DeviceInfo getDevice(int position) { + return devices.get(position); + } + + public DisplayService.DeviceInfo getDevice(String address, boolean create) { + for (DisplayService.DeviceInfo device : devices) { + if (device.address.equals(address)) { + return device; + } + } + + DisplayService.DeviceInfo deviceInfo = null; + if (create) { + deviceInfo = new DisplayService.DeviceInfo(address, 0); + devices.add(deviceInfo); + } + return deviceInfo; + } + + @Override + public int getCount() { + return devices.size(); + } + + @Override + public Object 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) { + ViewHolder viewHolder; + + if (view == null) { + view = inflater.inflate(R.layout.listitem_device, null); + viewHolder = new ViewHolder( + (TextView) view.findViewById(R.id.device_name), + (TextView) view.findViewById(R.id.device_address), + (TextView) view.findViewById(R.id.device_rssi), + (TextView) view.findViewById(R.id.device_isDisplay)); + view.setTag(viewHolder); + } else { + viewHolder = (ViewHolder) view.getTag(); + } + + DisplayService.DeviceInfo state = devices.get(i); + if (state.name != null && state.name.length() > 0) { + viewHolder.deviceName.setText(state.name); + } else { + viewHolder.deviceName.setText(R.string.unknown_device); + } + viewHolder.deviceAddress.setText(state.address); + + viewHolder.rssi.setText(getText(R.string.rssi) + ": " + + (state.rssi != 0 ? valueOf(state.rssi) : getText(R.string.rssi_unknown))); + + viewHolder.isDisplay.setText("Is display: " + + (state.isDisplay != null ? state.isDisplay : "unknown")); + view.setClickable(state.isDisplay != null && state.isDisplay); + + return view; + } + } +} -- cgit v1.2.3