What I really want to do at this point is support multiple routes, but I'm (more than) a little bit annoyed by how the app behaves on the watch itself. First, a screen appears that has an "IQ" logo and the words "metrolink-watch". Then the screen goes blank. For quite a while. Sometimes forever.
My interpretation of this is that the first of these is a splash screen which (hopefully) I can configure. If I can, I should.
Then there is a delay while the query for the data happens, during which time the screen is blank; we should change that. I believe that generally we will get some answer back, even if it is that the query timed out, so the "forever" is probably when the query fails but we don't handle the response properly.
In fact, there are two possibiities: there is an error of some form which we should report; or there is simply no data, which should be interpreted as "no trams currently running on those routes", which we should explain.
Splash Screen
Tackling the splash screen first, there are a couple of parameters in the manifest which enable you to configure how this looks. The name is a reference to a string resource, and the launcherIcon is a reference to a drawable resource. Hopefully if I configure those, I can get a picture of a nice yellow tram and the words "Tram Info" to appear.I downloaded an image from the internet with the Bee Network logo and saved it as metrolink.png. I then changed the drawables.xml resource file to reference this. Then in strings.xml I changed AppName to be Next Tram, which is the information which this app is intended to provide.
<drawables>Since the splash screen does not appear in the simulator (it shows a blue triangle while loading the widget), I compiled it and downloaded it onto the watch. I understand that it is both important to verify apps that are downloaded and that it is going to be slow on a low-power device, but it is painful to sit and wait for it to happen. This is not my kind of development cycle. Eventually, however, I can see an icon (it's somewhat indistinct, so I think I'll ultimately be designing something else) and the words Next Tram.
<bitmap id="LauncherIcon" filename="metrolink.png" />
</drawables>
<strings>
<string id="AppName">Next Tram</string>
</strings>
I have checked those changes in as METROLINK_MC_SPLASH_SCREEN.
Status
But that only lasts for a moment before the screen goes completely black. I suspect that this is the moment it renders my view. So, by the time onUpdate returns, I need to have displayed a message saying "Please Wait, Loading Data..." or some such. At the same time, it's very important that this message does not scribble over existing data when we are re-loading the data from the server.So I'm going to add a variable showWait which is initially true; if this is true in onUpdate, the waiting message will be shown and the showWait variable set to false. I don't fully understand the lifecycle yet, so I'm going to assume that setting it in initialize is reasonable enough. If it doesn't work the way I expect, I will come back and do something differently.
using Toybox.Timer;This is checked in as METROLINK_MC_PENDING_SCREEN.
class metrolink_watchView extends WatchUi.View {
var showWait;
var route;
var textArea;
var timer as Timer.Timer?;
function initialize(route as Route) {
self.showWait = true;
self.route = route;
View.initialize();
}
// Update the view
function onUpdate(dc as Dc) as Void {
if (showWait) {
textArea.setText("\n\nPlease Wait.\nLoading Data...\n");
showWait = false;
}
if (timer == null) {
var params = {};
if (route.from) {
In order to handle the error screen, I temporarily fiddle with the route information to make it impossible to find any trams. Running the app again, it just sits there saying "Please Wait...". Not what we want.
Because of the way in which PHP represents associative arrays, an empty dictionary is indistinguishable from an empty array, and json_encode encodes it as an empty array. Consequently, in onReceive, we can spot "no trams found" case as an array rather than a dictionary. We already test for this case so that assembleMessage does not fail. So we will simply display a different message which explains that no trams could be found for the specified route.
Finally, if we receive an error code, I am going to display a message that doesn't explain anything but includes the response code. Hopefully knowing that an error happened is enough, since there probably isn't anything you can do right now.
if (responseCode == 200) {Checked in as METROLINK_MC_ERROR_CONDITIONS.
if (data instanceof Dictionary) {
textArea.setText(assembleMessage(data));
} else {
textArea.setText("\nNo trams currently found on the\n" + route.name + "\nroute");
}
WatchUi.requestUpdate();
} else {
textArea.setText("Error querying server.\nResponse Code:\n" + responseCode + "\nroute\n" + route.name);
}
No BLE Connection Available
The moment I put this onto the watch, I see an error message, code -104. Comparing this to the list of constants in $Toybox.Communications$, I see that it says that it is because there is no BLE Connection Available. In other words, the watch needs to talk to my phone and can't.This is odd, because my watch is receiving other phone notifications, and it hasn't had this problem before. But I'm not really here to try and debug my watch (or phone), but to make an app. And it seems that, in spite of saying above that I wasn't going to try and identify all the different cases, this one is special enough that I want to have a special message for it. I know that the moment I do this, the situation will never arise again and I will not see the message - but I can force it to happen by turning off bluetooth on my phone.
switch (responseCode) {Checked in as METROLINK_MC_NO_BLE_ERROR.
case Communications.BLE_CONNECTION_UNAVAILABLE:
msg = "\nCannot connect to phone using Bluetooth";
break;
default:
msg = "Error querying server.\nResponse Code:\n" + responseCode + "\nroute\n" + route.name;
break;
}
No comments:
Post a Comment