Dashboard for Pebble is now version 1.13. This version contains a new Materially design, as well as fixes to the Data and ringer toggles as a result of the changes in Android 5.0 Lollipop.

The major point to note is that the method reflection I was using to implement the Data relied on an internal API in the ConnectivityManager class (which has existed in Android since very early versions). This API has since been moved to a more system-exclusive location (the Telephony class) that cannot be invoked using method reflection and as such the feature stopped working on Android 5.

Being one of the main features of Dashboard (and half the sole purpose in the original Data Toggle watchapp), this outcome was unacceptable. After searching for an alternative and finding nothing but similarly disgruntled Android developers, I came across a widget developer named Cygery who had found a way to implement this behavior in Android 5, and after a brief email exchange I was informed of his method, which was quite ingenious.

As a result, full functionality has been restored on Android 5, but at a large price – the feature now requires root privileges to change that particular settings. This is obviously not ideal, but the only way I can see the feature working beyond Android 5. Users on KitKat and below remain unaffected and the app should work as it did for them. Therefore, the Dashboard Android app will request root when it starts, as well as post a notification if the Data toggle is used and root access is not given. Most SuperUser apps will allow this access to be given on a per-app basis, so please allow this if you are a Android 5 user and need to use the Data toggle.

Download

Get it on Google Play

Over the last week, there have been have been four version of Dashboard released (9, 10, 11 and now 12) following the inclusion of the Wakeup API. I used this shiny new firmware feature to let users of Dashboard schedule daily wakeups to issue an on/off command to the Dashboard Android app, at times they would use the toggles anyway.

pebble-screenshot_2014-11-08_21-37-47    pebble-screenshot_2014-11-08_21-38-04

pebble-screenshot_2014-11-08_21-38-11    pebble-screenshot_2014-11-08_21-38-21

A new ‘HOLD’ icon prompts access to the scheduling feature, including list of existing events and UI to create new ones.

A personal example of this is that every night at about midnight I turn off WiFi on my phone to save power through the night using Tasker. Now, I can remove the Tasker icon from the status bar and use Dashboard to carry out the action instead. Of course, Tasker didn’t require me to keep my Bluetooth on overnight, but it’s a small price to pay for automated control of Android radios!

When adding such a complex feature (Dashboard itself went from two main code files to eight and ~600 to ~1300 lines of code), bugs will occur. Some will be code-based, such as not handling setting two wakeups for the same time (which the system will not allow) and warning the user, and some are behavioral.

At the moment, the Pebble appstore will not always update the released watchapp when a new version is uploaded. This can make co-ordinating a release with Google Play Store very difficult. Users were prompted to ‘update watchapp from Android app’. What I intended was for them to use the ‘Install Watchapp’ button in the Dashboard Android app to get the bundled compatible version, but in reality they were unloading and reloading the watchapp from the Pebble app locker, which ended up with them still having the old version. And so the loop continued until some concerned users emailed me about it. In all cases I clarified the correct procedure and every case was fixed. So now that process is hopefully a bit more explicit!

For a couple of my existing watchapps and watchfaces I have implemented a smooth animation using an AppTimer. This involves something like the snippet below:

static void some_layer_update_proc(Layer *layer, GContext *ctx) {
  // Graphics calls

}

static void timer_handler(void *context) {
  // Update frame
  layer_mark_dirty(some_layer);

  // Finally schedule next frame
  app_timer_register(34, timer_handler, NULL);
}

...

static void start_animation() {
  // Schedule first frame to start loop
  layer_set_update_proc(some_layer, some_layer_update_proc);
  app_timer_register(34, timer_handler, NULL);
}

As you can see, after the first frame is scheduled with an AppTimer, the timer’s handler schedules the next, and so an infinite loop is born. After implementing this multiple times, it occurred to me that I could make this process easier to set up, even if it was just for myself.

The result of this is a new library called pge, which creates an object that handles this looping of game logic and rendering per-frame for you, similar to STL. It also handles button clicks with an easier abstraction for the developer. Here’s a quick example of usage, from the GitHub README file:

#include "pge.h"

static PGE *s_game;

void loop() {

}

void draw(GContext *ctx) {

}

void click(int button_id) {

}

...

s_game = pge_begin(s_window, loop, draw, click);

This will start a 30 FPS loop that calls the developer’s implementation of draw() and loop() every frame, and click() when a button is clicked. The developer can then check the button ID as usual using the Pebble SDK constants, such as BUTTON_ID_UP. The loop will end and the PGE can be destroyed as part of a normal Window‘s lifecycle:

static void main_window_unload(Window *window) {
  // Destroy all game resources
  pge_finish(s_game);
}

The GitHub repo also includes a sample app where I implemented a simple ‘game’ of controlling a ‘robot’, using select to start/stop the robot and the up and down buttons to rotate its direction of travel.

Robot game

I’m currently working on implementing an Entity object that can be added to a list for automatic looping and rendering by the PGE. This will eventually also allow collision, as well as couple of other useful features.

If you are thinking of creating such a game, this library can hopefully help get you started. Let me know when you end up creating! The repo can be found here.

A while ago I created a simple Alert Library, which provides functions to show and hide a set of layers to show an ‘alert window’ for a time that tells the user of an event without changing Window.

screenshot

Continuing this theme, today I created another similar library called the ToastLayer, which has two advantages over the Alert Library:

1. The toast notification animates up from the bottom, instead of covering the majority of the Window.

2. It is designed as an object, like any of the other Layers in the Pebble SDK. This means there can be more than one!

Feel free to use it to show notifications without changing Window! I will probably look into including this in some of my existing apps.

Not a lot has been happening on this blog for the last few weeks, and the reason for that is that I have been busy beginning my internship at Pebble! It’s been a great experience so far (We released SDK 2.5 today!) and I can’t wait to work on more awesome things to help make Pebble even more useful smartwatch.

That being said, I’ve been able to find time to maintain and update my public Pebble apps at weekends, and hope to continue this pattern whenever I can, because I have some ideas I want to implement even just for myself.

A result of this is a new application of my Spark Core driven LCD project in collaboration with a new colleague to display social media trends from WhatTheTrend on animated cards on Pebble, and as an added bonus show the same information on the LCD display.

After some teething issues, it was eventually presentable and works pretty well – but for some reason only on Wi-Fi. Here’s a photo of the whole thing in action. (Eduardo Sasha is imprinted on my brain now from all the testing…)

image

Stay tuned for coming updates to Dashboard and Wristponder, as well as bringing Watch Trigger up to date as well!

Just released Dashboard 1.3!

The major new feature in this version is the ability to dynamically re-order the toggles to suit your preference. The way this works involves selecting each position in an Android Spinner in the ‘Configure’ tab:

Screenshot_2014-09-07-19-46-17

 

Each time a user makes a selection in one of the positions, the rest of the Spinner array is checked to look for a duplicate of the toggle the user has just chosen, and switches the two around. For example, if the user changes the Wi-Fi toggle to Autosync, the first toggle becomes Autosync and then the existing Autosync Spinner duplicate is changed to the only other missing toggle type – Wi-Fi!

This means that the toggles can be any order possible, such as the examples below:

toggle-config

That’s a total of P(8,8) = 40320!

 

A not insignificant amount of time after starting work on this update, it is finally here!

New features include:

- All data to be synchronised is now done in a streaming manner after each Window appears, meaning no more waiting for sync!
– Favourite contacts are now chosen using the Android Contact Picker, and not from five (potentially very large) spinners.
– The debug log can now be read and reported from the Settings screen. This makes reporting bugs to me much simpler.

Here’s a before and after shot of the Favourites selection Activity:

favourite-selection

There is only really one major comment to make that arose during development for this version, and that’s on the subject of an Android Activity in KitKat. I came across a a strange behaviour when launching the Pebble Android app to install the watchapp. It appears that in the event that the user chooses ‘Install Watchapp’ from Wristponder Settings, completes the installation and returns to the Settings Activity, they will not be able to launch any new ones such as Favourites or Import for anywhere between 10 to 45 seconds. On top of this any spamming of buttons done by a bemused user results in just as many launches when the Activitys requested are eventually delivered.

The only evidence of this in a single logcat output something along the lines of “Waited long enough for ServiceRecord” (unable to reproduce it at the time of writing, which is a good thing!) and this is the only link I can find on the subject. Apparently its to do with serializing launches from background services, although none of my launches are Services.

Anyway, that is the only problem with this release, and I feel that Wristponder is now a pretty solid and smooth piece of software. For this I am proud!

Download
Get it on Google Play

Follow

Get every new post delivered to your Inbox.

Join 183 other followers