Nov 11

Factory Method in Swift

protocol AbstractObject {
    static func create() -> AbstractObject
    func doStuff()
}

extension AbstractObject {
    func doStuff() {
        let className = String(describing: self)
        print("\(className).doStuff()")
    }
}

class ConcreteObject: AbstractObject {

    private init() {}

    static func create() -> AbstractObject {
        return ConcreteObject()
    }
}

class SteelObject: AbstractObject {

    private init() {}

    static func create() -> AbstractObject {
        return SteelObject()
    }
}

let concrete = ConcreteObject.create()
let steel = SteelObject.create()
concrete.doStuff()
steel.doStuff()
Oct 26

GreenRobot’s EventBus has a number of benefits compared to local broadcasts. Like broadcasts, events are a tool for decoupling your application architecture, and they’re especially useful when handling responses to asynchronous requests. EventBus makes it possible to receive results on specific threads and is also easier on the keyboard because it requires you to write less boilerplate code.

Note that discussion here only concerns broadcasts sent using LocalBroadcastManager, i.e. broadcasts that are sent and received only within the same process. System-wide broadcasts sent using Context.sendBroadcast() are not covered.

There’s an accompanying example app on GitHub. The app explores only the performance of EventBus in relation to local broadcasts when sending multiple events/broadcasts in succession (i.e. in a for-loop). For single events/broadcasts sent only sporadically, performance of the event/broadcast delivery itself is a non-issue. Furthermore, you can usually rearrange your event delivery to happen in bigger batches if performance, CPU and battery usage is an issue (which is basically always :) Therefore, you should not base your decision whether to use the EventBus library on the example code alone.

Event delivery on specific threads

You can select whether to receive EventBus events on different threads based on the threadMode setting you (optionally) specify in the @Subscribe annotation, as described in the EventBus documentation). Make sure you check out the documentation, since threadMode behavior may not be immediately obvious based on the name alone. Here are some scenarios where you might want to choose a specific threadMode over others:

  • @Subscribe(threadMode = ThreadMode.POSTING) The only mode that’s always guaranteed to be synchronous. You may want to use this e.g. to update the UI if you know you’re already on the main thread, or continue some background work on a worker thread. This is the default setting if you don’t specify the mode at all.
  • @Subscribe(threadMode = ThreadMode.MAIN) You can use this to update the UI when work completes on a background thread.
  • @Subscribe(threadMode = ThreadMode.BACKGROUND) For handling events on a dedicated worker thread one-by-one. When posting subsequent events from outside the worker thread while work is still ongoing, further requests will be queued. Note that if you’re already on the worker thread, any further events posted using this mode will be posted synchronously. If you need to post an event asynchronously from the event handler, consider using the ASYNC mode instead.
  • @Subscribe(threadMode = ThreadMode.ASYNC) This option is useful when you need to handle multiple callbacks concurrently, like when executing multiple network requests. The calling thread is from a separate ThreadPool of worker threads, and never the posting thread. Remember to be careful with this in your event handler, since multiple threads may be executing the code asynchronously.

By contrast, BroadcastReceiver’s onReceive() is always called on the process’ main thread, unless you call sendBroadcastSync() from some other thread which, as the named implies, is executed directly.

Callback registration

To register callbacks that you want EventBus to call when certain types of event objects are posted, you specify the posted object type as parameter to your callback methods. You also need to register the object of the class where your callbacks are implemented. This is roughly equivalent to registering a broadcast receiver with a set of intent filters, as shown in this example:

public class MyActivity extends Activity {  // ...

    private MyReceiver myReceiver = new MyReceiver();
    private static final BROADCAST_ACTION = "BROADCAST_ACTION";

    @Override public void onStart() {
        super.onStart();
        LocalBroadcastManager.getInstance(this)
            .registerReceiver(myReceiver, new IntentFilter(BROADCAST_ACTION));
        EventBus.getDefault().register(this);
    }
    
    @Override public void onStop() {
        EventBus.getDefault().unregister(this);                  
        LocalBroadcastManager.getInstance(this).unregisterReceiver(myReceiver);
        super.onStop();
    }

    @Subscribe public void onEvent(MyEvent event) {
        // Do stuff with received event ...
    }

    private static class MyReceiver extends BroadcastReceiver {
        @Override public void onReceive(Context context, Intent intent) {
            // Do stuff with received broadcast ...
        }
    }
}

As you can see, writing a broadcast receiver is somewhat more cumbersome since you need to extend the BroadcastReceiver class and supply an intent filter, whereas you can just annotate your event handling methods with @Subscribe when using EventBus.

Posting events and broadcasts

This is an area where LocalBroadcastManager and EventBus are very similar to each other, without much boilerplate even with LocalBroadcastManager:

public void postEvent() {
    MyEvent event = new MyEvent();
    EventBus.getDefault().post(event);
}

public void sendBroadcast() {
    Intent intent = new Intent("my_action");
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

Delivering content

With broadcasts, you need to package your payload using intent extras, which can often require quite a bit of boilerplate code, especially when using Parcelables. With EventBus you can place your content within the event object itself. This requires no cumbersome packaging, no parcelables, etc. The content of the event you post is delivered as-is to the callback handler. Let’s expand the methods in the previous section to supply some payload as well:

class MyObject {
    public void doStuff() {
        // ...
    }
}

class MyEvent {
    int value;
    String text;
    MyObject myObject;

    public MyEvent(int value, String text, MyObject myObject) {
        this.value = value;
        this.text = text;
        this.myObject = myObject;
    }
}

public void postEvent() {
    MyEvent event = new MyEvent(123, "abcdef", new MyObject());
    EventBus.getDefault().post(event);
}

public void sendBroadcast() {
    Intent intent = new Intent("my_action");
    intent.putExtra("int_extra", 123);
    intent.putExtra("text_extra", "abcdef);
    intent.putExtra("myobject_extra", new MyObject());
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

Passing the example instance of MyObject to a broadcast intent is not as simple as it looks, since the MyObject class needs to implement the Parcelable interface as specified in Android documentation. (Note that you should really use constant definitions for names of extras, they’re literals above only for conciseness and clarity.)

With EventBus, you can use the posted event directly in your callback handler, whereas with broadcasts you first need to unpack the payload from extras in your broadcast receiver:

@Subscribe
public void onEvent(MyEvent event) {
    Log.d(TAG, "value: " + event.value);
    Log.d(TAG, "text: " + event.text);
    Log.d(TAG, "myObject.doStuff(): " + event.myObject.doStuff());
}

// ...

private static class MyReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    int value = intent.getIntExtra("int_extra", -1);
    String text = intent.getStringExtra("text_extra");
    MyObject myObject = (MyObject) intent.getParcelable("myobject_extra");
    Log.d(TAG, "value: " + value);
    Log.d(TAG, "text: " + text);
    Log.d(TAG, "myObject.doStuff(): " + myObject.doStuff());
}

Conclusion

EventBus is a great library for decoupling your application architecture, delivering results on specific threads, and having to write no unnecessary boilerplate code when handling event payloads. While very convenient compared to simple local broadcasts, EventBus’ tradeoff comes in the lack of performance, although it’s still quite performant for most tasks. All things considered, for most intents and purposes EventBus is a very good choice due to its versatility.

This article was also published at my employer’s blog at https://bitfactor.fi/en/2016/11/01/comparison-of-eventbus-and-androids-local-broadcasts/

Nov 08

To access Bluetooth Low Energy (aka Bluetooth Smart) devices from an iOS or Android device it’s useful to know a bit of related terminology first.

GAP (Generic Access Profile) is concerned with scanning and connecting to devices. GATT (Generic Attribute Profile) comes to play when you have connected to a device, and want to access its services and characteristics.

In the GAP context, the iOS/Android device usually acts as the central, while the BLE accessory is the peripheral. Note that the roles described here are conceptual, i.e. an iOS/Android device can act as a peripheral as well (with limitations), which can be really useful when e.g. generating data for testing.

When scanning for peripherals (i.e. listening to advertisements from peripherals), there are two specialized roles: observer and broadcaster. The broadcaster sends relevant information in its advertisement package to any observer that might be listening. In other words, a broadcaster doesn’t care how many (if any) observers there are listening to it’s advertisements at any given time. The iOS/Android device normally acts as the observer, and the BLE accessory is the broadcaster.

To send custom data to any device that may be listening, you can write such information to e.g. the manufacturer data field of the advertisement package. When only sending and listening advertisement packages (potentially with context-specific data), no connection needs to be established between the devices.

Be wary that both certain fields of the advertisement package may get cached. For example, the local name field tends to get cached on Android, and can therefore not reliably be used for broadcasting information that is bound to change.

The basic procedure for setting up a BLE connection is roughly as follows:

1. Scan devices advertising specific services
2. Connect to a device
3. Discover service(s)
4. Discover characteristic(s)
5. Register for characteristic notifications

To connect your central to a peripheral (steps 1 & 2) in order to e.g. read and write data only between the two devices, you start the connection process by scanning for peripherals that provide a specific service (or services) you require. In a viable situation where there are multiple peripherals advertising themselves in the vicinity of a central device, you may want to send customized identifier in the advertisement package (therefore fulfilling the broadcaster role, see above) so that the central can observe the sent identifiers and distinguish a particular peripheral from others.

Steps 3 to 5 are covered by GATT, which comes into play when you have actually established a connection with a BLE peripheral. Once connected, you can scan the peripheral’s services and their related characteristics.

A BLE device profile consists of one or more services, each of which can have one or more characteristics. A common case is that there’s one service, which has one characteristic for reading, and one for writing. Services are basically a logical collection of read/write characteristics. Each service and characteristic is identified by a 16/128-bit unique identifier. The 16-bit identifiers are defined by Bluetooth SIG to ensure/encourage interoperability between BLE devices as needed, and 128-bit indentifiers are available for building customized services/characteristics. Each characteristic can also have descriptors that can describe the characteristic’s value, set minimum/maximum limits, or whatever you may need. Dealing with descriptors is normally not necessary, except in one particular case on Android that will be covered later.

You can read a characteristic’s current value, or register to get notified when the value changes. Notifications allow you to get updates whenever they happen, instead of polling the current value repeatedly. When writing to a characteristic, it’s possible to get confirmation of a successful write operation, assuming the characteristic has been configured to support this on the peripheral.

iOS Implementation Details

Communication with BLE devices on iOS is handled using the Core Bluetooth framework. You start the connection process by initializing an instance of CBCentralManager, supplying a CBCentralManagerDelegate as argument to the initializer. When initialization is complete, Core Bluetooth calls your delegate’s centralManagerDidUpdateState() method, where you can take further action as needed.

In case everything is OK, CBCentralManager’s state property will be PoweredOn. If, however, the user has Bluetooth turned off (state PoweredOff), they will be presented at this point with a dialog requesting to turn it on.

After initializing the CBCentralManager instance, you can start to scan for devices by first setting up a CBCentralManager delegate, and then starting the scan by calling CBCentralManager‘s scanForPeripheralsWithServices() method, where you pass an array of CBUUID objects representing BLE services the scanned peripherals must provide. Often there is just one service, but more complex devices may have more.

Once a matching peripheral is found, Core Bluetooth calls the didDiscoverPeripheral() delegate method. (Note that the actual function name is much more convoluted, mostly due to legacy reasons, but this and other delegates are commonly known by these shortened forms.) Here you can read the discovered device’s advertising data. In case your required data is already contained in the advertisement packet, you can extract it here and continue to listen to further advertisements. Advertisement data can also contain information you need to figure out if you want to connect to the discovered device. Note that you need to store the CBPeripheral object locally, otherwise it gets deinitialized.

To initiate connection, call the connectPeripheral method of your CBCentralManager. When connected, Core Bluetooth calls your central manager delegate’s didConnectPeripheral() method, where you can set up a CBPeripheralManager delegate and start discovering services on the peripheral by calling discoverServices() on the CBPeripheral object.

Once service discovery is complete, Core Bluetooth calls your CBPeripheralDelegate‘s didDiscoverServices() method. Once you have discovered the service you’re interested in, you’ll want to discover its characteristics by calling discoverCharacteristics() on the CBPeripheral object. Once complete, you’ll get a call to the didDiscoverCharacteristicsForService() method. Here you can e.g. register to be notified on changes to a readable characteristic’s value, or store a writable characteristic for further use.

To listen to notifications when a readable characteristic’s value changes, call setNotifyValue() on the CBPeripheral object, with the characteristic as argument. Note that for this to work the characteristic must be configured to support notifications on the peripheral. When a characteristic’s value is subsequently updated, Core Bluetooth will call your CBPeripheralDelegate‘s didUpdateValueForCharacteristic() method. You can read the current value of the characteristic from the CBCharacteristic parameter’s value property as NSData.

Writing data to a characteristic is done by calling the writeValue() method on the CBPeripheral object. You can choose to either get a write result (in case the peripheral supports it), or ignore it. In the former case, your CBPeripheralManager‘s didWriteValueForCharacteristic() gets called with the result of the write operation.

Android Implementation Details

Bluetooth LE on Android is a bit of a wild west, especially when dealing with proprietary Bluetooth stack implementations, but here’s the general idea on how to get started using the public API. First you need to request both BLUETOOTH and BLUETOOTH_ADMIN permissions in your app’s manifest. High-level Bluetooth operations are done through the BluetoothAdapter instance, which is common to all apps on the system. You can get the instance through BluetoothManager‘s getAdapter() method.

Scanning peripherals requires that you have implemented the callback interface for getting scan results. In case you need to support API levels 18 to 20, call BluetoothAdapter‘s startLeScan() and supply an instance of BluetoothAdapter.LeScanCallback implementation. For API levels 21 onward, first call BluetoothAdapter's getBluetoothLeScanner() to get an instance of BluetoothLeScanner, and then call startScan() on the instance, supplying a ScanCallback where you can handle scan results. Also note that to get scan results on Lollipop (5.0) and newer you will need to declare ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission in the manifest.

In your ScanCallback‘s onScanResult() you can get the peripheral from the supplied ScanResult by calling getDevice(), which returns a BluetoothDevice object. To initiate connection, call connectGatt() on the instance, giving a BluetoothGattCallback instance as argument.

Your BluetoothGattCallback‘s onConnectionStateChanged() is called, as the name implies, when the connected to or disconnected from the peripheral. Once you’ve established connection, call discoverServices() on the supplied BluetoothGatt instance. This will result in a call to onServicesDiscovered(), where you can set up read and write characteristics as needed.

You can get a BluetoothGattService instance by calling getService() on the supplied BluetoothGatt object. To register to notifications when a characteristic’s value changes on the peripheral, call setCharacteristicNotification() with true as argument on the BluetoothGattCharacteristic object you get by calling getCharacteristic() on the service instance. An important thing is to also remember to enable notifications on the Client Characteristic Configuration descriptor by calling setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) on the descriptor instance. You can get the descriptor by calling getDescriptor() on the BluetoothGattCharacteristic object, supplying the UUID of the descriptor (whose Bluetooth SIG assigned number is 0x2902. Incidentally, on iOS this is done automatically for you.)

When a characteristic’s value is changed on the peripheral and you’ve registered to get notifications for the characteristic, your BluetoothGattCallback‘s onCharacteristicChanged() is called by the framework, and you can then get the current value by calling getValue() on the supplied BluetoothGattCharacteristic object.

Writing to a writable characteristic is done by first setting the required data to the BluetoothGattCharacteristic object using one of the setValue() overloads, and then calling BluetoothLeGatt‘s writeCharacteristic() to send the data over to the peripheral. You can get results of the write operation to BluetoothGattCallback‘s onCharacteristicWrite() method if you’re interested in them.

So, there you have it. A few relevant links for more information:

May 08

Interesting.

func doStuff(arr: Array) {
    var value: UInt8!// = 0
    let data = NSData(bytes: arr, length: arr.count * sizeof(UInt8))
    data.getBytes(&value, range: NSMakeRange(0, 1))
    println(value)
}

let arr: [UInt8] = [ 0x00, 0x34, 0x56, 0xFF ]
doStuff(arr)

value will be nil if 0x00 is read from NSData. In case value is not declared as Optional, 0 is read instead. Just something to keep in mind.

Apr 22

1. Build the project, e.g. gradlew build
2. Go to the directory you want to place the headers (e.g. src/main), and execute:

javah -d jni -classpath ~/Library/Android/sdk/platforms/android-22/android.jar:../../build/intermediates/classes/debug {fully.qualified.class.name}

This will place the auto-generated headers in the src/main/jni directory. Change the platform version in front of android.jar as appropriate.

Apr 24

Perhaps not broken, but documented inadequately. In http://developer.android.com/training/implementing-navigation/temporal.html there’s a simple guide on how to set up back stack navigation when opening an app e.g. from a notification using a “deep link” to an activity that is not the topmost one in the app, so that the user can navigate upwards in the stack by pressing the back key.

Having wasted a couple of hours trying to make this work in LoanShark, I finally noticed a warning in LogCat:

W/ActivityManager﹕ Permission Denial: starting Intent [...] not exported from uid 10131

What the documentation forgot to mention is that you need to set the activity you want to jump to from e.g. a notification as exported. I added the attribute and encountered no more problems. The weird thing is that it did actually sometimes work even without the exported attribute… strange indeed. But now it works 100% of the time, fortunately.

Apr 16

I’m currently in the process of making the landscape support in LoanShark more robust. When in portrait mode, the main activity displays a list of loans, while the view loan activity, opened by selecting an item from the list, displays the selected loans’ details. In landscape orientation both views are visible. These are all implemented using fragments, i.e. the activities themselves only provide the layout to glue the fragments together.

When holding the device in portrait mode, the loan view displays loan details using the same fragment class as is used on the right-hand side in landscape orientation. When the user is viewing a loan in portrait (view loan activity), and rotates the device to landscape (to main activity), the same loan is displayed.

The problem I’ve come across is that since fragment objects belong to a single Activity (stored in the Activity object’s own FragmentManager instance), there’s no way to reuse the fragment that’s seen in portrait mode of the view loan activity on the right-hand side of the landscape layout in the main activity. The reason is that when the user rotates from portrait to landscape, the activity hosting the loan details is destroyed, which in turn destroys the fragment as well.

To keep my fragment implementations modular (to break direct dependencies between them), I’ve utilized callbacks to the hosting activity class when loaders have finished their jobs. This way I’m able to know e.g. when a loan’s details have been finished so that the fragment can be created.

My initial implementation (and the one being used in version 2.2.0) is that the old fragment that was created when in landscape mode is displayed briefly before being replaced with the loan that was selected in portrait mode. This is clearly suboptimal because there’s a clear visual anomaly, however brief, when rotating the device. I considered patching the problem by hiding the existing fragment in landscape,  thus preventing the old fragment from being shown before fading in the fragment when then the new loan would have been loaded. That wouldn’t have been a solution I would’ve been satisfied with, so clearly more thinking was needed.

When a loan has been loaded in portrait mode and is about to be displayed in the view loan activity, I store the loan data in the main activity as well (and make sure it’s saved in onSaveInstanceState() in case the activity is destroyed while viewing the loan data). Then, if the user rotates the device to landscape, I check if the view loan fragment already exists (in case the device has been in landscape mode previously, it does). In such a case, I set the selected loan’s data to the existing fragment. When the activity’s onCreate() finishes, the fragment’s onCreateView() is called, and it’s there that the loan data can then be reused.

Nothing of this sort is mentioned in documentation concerning fragments. Also, it’s quite difficult to find solutions to fragment problems by googling them; all you seem to get is countless beginner tutorials on how to use fragments. I came across this solution after spending a couple of nights figuring out how the fragment management works internally, and from there I had an idea how to go on about solving the problem.

Apr 03

TextView with italics text gets cropped at the rightmost edge when the view is set to wrap_content. Reportedly this affects when the content is set to have gravity=”right” as well.

http://stackoverflow.com/q/4353836

I haven’t plunged into the source code on this one, but it seems that Android’s layout engine evaluates the TextView’s width based on the text baseline, and does not take into account the fact that skewing the text may result in the projected baseline at the top (whatever it could be called) may not be the same. The solution is to simply add a space character at the end of the string.

I ran into this problem when designing the card layout for LoanShark loans. I wonder how many applications’ layouts would break if there was to be an actual fix to this problem…

Mar 21

Putting this here for reference:

export PS1="\t \w\e[1;36m\$(__git_ps1) \e[0m\$ "
Dec 06

If you’ve been dealing with Android fragments, odds are you’ve used the FragmentTransaction.addToBackStack() method. Often this method is called with a null argument, and that’s fine for most uses. Afterwards, you can pop the top of the back stack by calling FragmentManager.popBackStack() and you’re done.

You might be wondering what use is the String parameter in the addToBackStack() method. It can be quite useful in cases where you need to pop a number of items from the FragmentManager back stack at once. For example, you may want to wipe the slate clean of all fragments that you’ve been adding/replacing. You can do this as follows:

    FragmentManager fragMan = getFragmentManager();
    for (int i = 0; i < fragMan.getBackStackEntryCount(); ++i) {
        fragMan.popBackStack();
    }

Now, in case you want to leave one or more items on the back stack instead of popping the whole lot, you could try to keep track of the number of back stack items to pop, but this is tedious and error-prone to say the least. Here’s where addToBackStack()’s String argument comes to play. The String argument is the name of a back stack “state” you want to keep track of.

Let’s say that you have a two-pane layout, and on the right side you have a fragment that you’ve replace()d to a layout element. You’d like to keep this fragment visible at all times. You then proceed to utilize other fragments as well in the same layout spot, calling FragmentTransaction.replace() in the process, along with addToBackStack(). If you then want to pop all other back stack items but the first one, you can do this by adding a predefined state name to the first fragment’s addToBackStack() method:

    private static final String INITIAL_FRAGMENT_STATE = "initial_fragment_state";
    // ...
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    ft.replace(...);
    ft.addToBackStack(INITIAL_FRAGMENT_STATE);

Then, when you need to wipe the slate clean and lose all but the initial state from the back stack:

    getFragmentManager().popBackStack(INITIAL_FRAGMENT_STATE);

And there you have it. No need to keep track of the number of fragments in the back stack in each valid state of the application or any such nonsense. Just make use of named back stack states.

preload preload preload