{"id":1791,"date":"2013-09-30T19:11:15","date_gmt":"2013-09-30T07:11:15","guid":{"rendered":"https:\/\/www.deltics.co.nz\/blog\/?p=1791"},"modified":"2013-09-30T19:22:28","modified_gmt":"2013-09-30T07:22:28","slug":"developing-and-debugging-an-appwidget-part-2","status":"publish","type":"post","link":"https:\/\/www.deltics.co.nz\/blog\/posts\/1791\/","title":{"rendered":"Developing and Debugging an AppWidget &#8211; Part 2"},"content":{"rendered":"<span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">9<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span><p>In the <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/1774\">first instalment of this series<\/a>, I implemented the basic framework of a new appwidget and established a means by which I could debug the widget code.  Now it&#8217;s time to add some code worth debugging.<\/p>\n<p><!--more--><\/p>\n<p>You may recall that the aim of my widget is to display the battery charge level so the first order of business is to figure out how to read the battery level.<\/p>\n<p>It turns out that the means by which we obtain this information involves <strong>Intents<\/strong>.  On this occasion however, we shall be working with something called a &#8220;sticky intent&#8221;.<\/p>\n<h3>Sticky Intents<\/h3>\n<p>The normal procedure when consuming intents &#8211; as far as my current understanding goes &#8211; is to create or declare an intent filter that will match the required intent.  You then declare a receiver and wait for the expected notification to arrive at that receiver, together with the corresponding <strong>Intent<\/strong> object containing all the information necessary for the receiver to respond (or simply behave) appropriately.<\/p>\n<p>A <strong>sticky intent<\/strong> does not require you to register a receiver however.  At least, not a real one.<\/p>\n<p>You simply setup the <strong>IntentFilter<\/strong> that will match the intent involved and register a <strong>null<\/strong> receiver.  You then <em>immediately<\/em> are returned a reference to the sticky intent.<\/p>\n<p>Information about the device battery is one such sticky intent, and the corresponding action is <strong>ACTION_BATTERY_CHANGED<\/strong>.  So, let us first make sure we can get the required battery information, then we&#8217;ll worry about how to update the widget UI with that information.<\/p>\n<p>This code in the widget <strong>onUpdate<\/strong> method should do the trick:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n  method BatteryWidgetProvider.onUpdate(aContext: Context; \r\n                                        aWidgetManager: AppWidgetManager;\r\n                                        aIDs: array of Integer);\r\n  var\r\n    filter: IntentFilter;\r\n    battery: Intent;\r\n    level, scale: Integer;\r\n    pct: Float;\r\n  begin\r\n    filter  := new IntentFilter(Intent.ACTION_BATTERY_CHANGED);\r\n    battery := aContext.registerReceiver(NIL, filter);\r\n\r\n    level := battery.IntExtra[BatteryManager.EXTRA_LEVEL, -1];\r\n    scale := battery.IntExtra[BatteryManager.EXTRA_SCALE, -1];\r\n\r\n    pct := (100 * level) \/ scale;\r\n  end;\r\n<\/pre>\n<p>We create a new <strong>IntentFilter<\/strong> object for the standard <strong>ACTION_BATTERY_CHANGED<\/strong> action.  We then call <strong>registerReceiver<\/strong> on our context, passing a <strong>NIL<\/strong> reference for the receiver and the filter we just created and we get back the sticky intent holding the current battery state.<\/p>\n<p>From the battery <strong>Intent<\/strong> we can now extract the information we need which in this case is two values:  the battery level and the <em>maximum<\/em> battery level.  Somewhat confusingly this second value is called the scale.<\/p>\n<p>These two pieces of information are contained within the <strong>Extras<\/strong> Bundle of the sticky intent.  Each is an integer value whose names are among several defined as constants by the <strong>BatteryManager<\/strong> class, and there are a number of ways of extracting them.<\/p>\n<p>Incidentally, the <strong>BatteryManager<\/strong> class resides in the <strong>android.os<\/strong> namespace, so this is added to the uses list of the unit containing <strong>BatteryWidgetProvider<\/strong>.<\/p>\n<p>When implementing <strong>Intent<\/strong> support in my camera app, I used methods of the <strong>Extras<\/strong> Bundle itself, but on this occasion I am taking advantage of the fact that the <strong>Intent<\/strong> object itself provides methods for reading such values and in this case I have the option of using methods which allow me to supply a default value if the value I ask for does not actually exist.<\/p>\n<p>The Java method is <code>&lt;strong&gt;getIntExtra&lt;\/strong&gt;( &lt;em&gt;name&lt;\/em&gt;, &lt;em&gt;defaultValue&lt;\/em&gt; )<\/code> but as you can see, I am using the fact that Oxygene presents such methods as properties with accessor indices.<\/p>\n<p>So, with the battery level (<strong>BatteryManager.EXTRA_LEVEL<\/strong>) and the maximum battery level (<strong>BatteryManager.EXTRA_SCALE<\/strong>) calculating the percentage battery level is a simple matter of some basic arithmetic.<\/p>\n<p>Trying to run this widget throws up a problem, in the form of a runtime exception caught and presented to us by the debugger:<\/p>\n<figure id=\"attachment_1792\" aria-describedby=\"caption-attachment-1792\" style=\"width: 434px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-09-29-at-19.55.49-.png?ssl=1\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-09-29-at-19.55.49-.png?resize=434%2C103&#038;ssl=1\" alt=\"Android says &quot;No!&quot;\" width=\"434\" height=\"103\" class=\"size-full wp-image-1792\" srcset=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-09-29-at-19.55.49-.png?w=434&amp;ssl=1 434w, https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-09-29-at-19.55.49-.png?resize=300%2C71&amp;ssl=1 300w\" sizes=\"(max-width: 434px) 100vw, 434px\" data-recalc-dims=\"1\" \/><\/a><figcaption id=\"caption-attachment-1792\" class=\"wp-caption-text\">Android says &#8220;No!&#8221;<\/figcaption><\/figure>\n<p><em>I should confess that from the little bit of research I did before setting about implementing this widget, I already knew this would happen but wanted to show you the consequences.<\/em><\/p>\n<p>Now, I could not find any reference to &#8220;<strong>IntentReceiver<\/strong>&#8221; in the Android SDK and searching for it throws up only <strong>BroadcastReceiver<\/strong>.  There are some docs on the interwebs which appear to document a very early Android SDK with an <strong>IIntentReceiver<\/strong> <em>interface<\/em> and I wonder if this exception message is just perhaps a little out of date and should now say <strong>BroadcastReceiver<\/strong>.<\/p>\n<p>In any event, our <strong>AppWidgetProvider<\/strong> is a <strong>BroadcastReceiver<\/strong> and does indeed receive intents, so whatever this <strong>IntentReceiver<\/strong> actually refers to, it does seem to apply to my situation.<\/p>\n<p>So far our widget app contains one component &#8211; the AppWidgetProvider for our widget.<\/p>\n<p>For debug builds it contains a second component &#8211; my DebugActivity.<\/p>\n<p>But both of these declare an <strong>intent-filter<\/strong> and are thus both receivers of intents.  Any call made using the <a href=\"http:\/\/developer.android.com\/reference\/android\/content\/Context.html\">Context<\/a> of either of these components to <strong>registerReceiver<\/strong> is going to fail for the same reason.<\/p>\n<p>What we need is some other component that can be invoked directly without having to respond to an intent, and which has a <a href=\"http:\/\/developer.android.com\/reference\/android\/content\/Context.html\">Context<\/a> which can be used to call <strong>registerReceiver<\/strong> for the sticky intent required to get the battery information.<\/p>\n<p>Fortunately, there is just such a component type available:  A <strong><a href=\"http:\/\/developer.android.com\/reference\/android\/app\/Service.html\">Service<\/a><\/strong>.<\/p>\n<h3>Android, At Your Service<\/h3>\n<p>A <strong>Service<\/strong> can &#8211; and often does &#8211; support one or more intent filters, but a service does not <em>have<\/em> to and if it does not it can still be invoked directly by name if required.  This is exactly what we shall do in this case.<\/p>\n<p>First of all, we add a new class to the project, extending the Service class.  I called mine <strong>UpdateService<\/strong>.<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\ninterface\r\n\r\n  uses\r\n    android.app,\r\n    android.content,\r\n    android.widget;\r\n\r\n  type\r\n    UpdateService = public class(Service)\r\n    public\r\n      method onBind(aIntent: Intent): IBinder; override;\r\n      method onStart(aIntent: Intent; aStartID: Integer); override;\r\n    end;\r\n<\/pre>\n<p>I am only scratching the surface of Android Services here.  Mine is a very simple service which will obtain the information required to update our widget, do the update and then &#8230; well, I&#8217;m not entirely sure.  The service may simply die at that point, or it may sit around doing nothing until the OS kills it or it is invoked again.  I&#8217;m not entirely sure, but I don&#8217;t think it really matters.<\/p>\n<p>This service doesn&#8217;t need to worry about binding, but we do have to override the <strong>onBind<\/strong> method since it is <em>abstract<\/em> in the <strong>Service<\/strong> class.  For our purposes we simply return <strong>NIL<\/strong> from this method.<\/p>\n<p>The <strong>onStart<\/strong> override is where this service takes care of everything, and we will look at that shortly.  But first, with this <strong>Service<\/strong> looking after the actual business of performing the update, our widget <strong>onUpdate<\/strong> code then becomes a simple call to invoke this service:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n  method BatteryWidgetProvider.onUpdate(aContext: Context; \r\n                                        aWidgetManager: AppWidgetManager;\r\n                                        aIDs: array of Integer);\r\n  var\r\n    updateIntent: Intent;\r\n  begin\r\n    updateIntent := new Intent(aContext, typeof(UpdateService));\r\n    updateIntent.putExtra('ids', aIDs);\r\n\r\n    aContext.startService(updateIntent);\r\n  end;\r\n<\/pre>\n<p>To invoke a service by name we create an <strong>Intent<\/strong> using a constructor identifying the calling context and a reference to the service class to be invoked.  In Java this class reference would be obtained using what appears to be a static member of the <strong>Class<\/strong> type (<code>Class.class<\/code>) but which is in fact a bit of Java compiler magic.  In Oxygene the equivalent magic is the <strong>typeof()<\/strong> function.<\/p>\n<p>With our freshly constructed <strong>Intent<\/strong>, we can then add whatever information that service may require passed to it via that <strong>Intent<\/strong>.  In this case we provide the array of Widget ID&#8217;s being updated (the user might have placed multiple instances of our widget on their device and each has a unique ID).<\/p>\n<p>The <strong>Intent.putExtra<\/strong> method is a massively overloaded method (24 varieties!) which supports putting a huge variety of types of information &#8211; in this case an array of Integer &#8211; as named values into the Intent Extras Bundle.<\/p>\n<p>Once the intent is ready, we then pass it to the <strong>startService<\/strong> method of the context.<\/p>\n<p>We now have a widget provider that will invoke a service to update any widget instances when required.  So now let&#8217;s complete the update service itself.<\/p>\n<h3>Adding Updatability to the Update Service<\/h3>\n<p>First of all, for a service to update a widget is really quite trivial.  As mentioned in <a href=\"https:\/\/www.deltics.co.nz\/blog\/posts\/1774\">part 1<\/a>, widgets are updated by providing an updated layout representing the state of the widget at a point in time.<\/p>\n<p>The &#8220;snapshot&#8221; is presented to the widget in the form of a new RemoteViews object containing the complete, updated layout to be applied to the widgets being updated.  So, the <strong>UpdateService.onStart<\/strong> method is quite simple:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n  method UpdateService.onStart(aIntent: Intent; aStartID: Integer);\r\n  var\r\n    update: RemoteViews;\r\n    ids: array of Integer;\r\n  begin\r\n    update := buildUpdate(self);\r\n\r\n    ids := aIntent.Extras.IntArray['ids'];\r\n    AppWidgetManager.Instance[self].updateAppWidget(ids, update);\r\n  end;\r\n<\/pre>\n<p>We declare a <strong>RemoteViews<\/strong> object.  We will build this in a new method &#8211; to be called <strong>buildUpdate<\/strong> &#8211; accepting a reference to the current context (the service itself, i.e. <strong>self<\/strong>).  We will add this method next, but first a quick look at how the service updates the widgets with the new <strong>RemoteViews<\/strong>.<\/p>\n<p>First I extract the array of widget ID&#8217;s identifying the widget instances to be updated, from the <strong>Extras<\/strong> bundle of the <strong>Intent<\/strong> that started the service (remember, this array of ID&#8217;s was placed there by the widget provider when it invoked the service in the <strong>onUpdate<\/strong> provider method).<\/p>\n<p>I then obtain the appropriate instance of <strong>AppWidgetManager<\/strong> for the current context, conveniently provided for me in the <strong>AppWidgetManager<\/strong> class <strong>Instance<\/strong> indexed property (surprise, surprise: in Java it would be <code>getInstance(self)<\/code>).<\/p>\n<p>The <strong>AppWidgetManager.updateAppWidget<\/strong> method has a number of overloads for updating widgets by different identifying criteria.  In this case I can use the method that accepts an explicit array of widget ID&#8217;s.<\/p>\n<p>All that is left now is to implement the <strong>buildUpdate<\/strong> method to actually construct the updated widget UI.<\/p>\n<h3>Building the Update<\/h3>\n<p>We have already seen how to obtain the current battery level so we can put that code in our <strong>buildUpdate()<\/strong> method for starters:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n  method UpdateService.buildUpdate(const aContext: Context): RemoteViews;\r\n  var\r\n    filter: IntentFilter;\r\n    battery: Intent;\r\n    level, scale: Integer;\r\n    pct: Float;\r\n  begin\r\n    filter  := new IntentFilter(Intent.ACTION_BATTERY_CHANGED);\r\n    battery := aContext.registerReceiver(NIL, filter);\r\n\r\n    level := battery.IntExtra[BatteryManager.EXTRA_LEVEL, -1];\r\n    scale := battery.IntExtra[BatteryManager.EXTRA_SCALE, -1];\r\n\r\n    pct := (100 * level) \/ scale;\r\n  end;\r\n<\/pre>\n<p>Now all that&#8217;s required to is construct the <strong>RemoteViews<\/strong> object and update the layout with the battery information:<\/p>\n<pre class=\"brush: oxygene; title: ; notranslate\" title=\"\">\r\n  method UpdateService.buildUpdate(const aContext: Context): RemoteViews;\r\n  var\r\n    filter: IntentFilter;\r\n    battery: Intent;\r\n    level, scale, pct: Integer;\r\n  begin\r\n    filter  := new IntentFilter(Intent.ACTION_BATTERY_CHANGED);\r\n    battery := aContext.registerReceiver(NIL, filter);\r\n\r\n    level := battery.IntExtra[BatteryManager.EXTRA_LEVEL, -1];\r\n    scale := battery.IntExtra[BatteryManager.EXTRA_SCALE, -1];\r\n\r\n    pct := (100 * level) div scale;\r\n\r\n    \/\/ Build a remote view to update the widget UI\r\n\r\n    result := new RemoteViews(aContext.PackageName, R.layout.widgetlayout);\r\n    result.setTextViewText(R.id.lblInfo, pct.toString + '%');\r\n  end;\r\n<\/pre>\n<p>With such a simple layout for the widget UI, building the updated <strong>RemoteViews<\/strong> object is itself also very simple.<\/p>\n<p>First we construct a <strong>RemoteViews<\/strong> object, employing a constructor that identifies the layout resource that we wish to use.<\/p>\n<p>Again, we see a construct that would be familiar to an <strong>Eclipse<\/strong> or <strong>Android Studio<\/strong> Java developer.  The <strong>res<\/strong> folder in our project is represented in our application by the <strong>R<\/strong> object, the <strong>layout<\/strong> folder by the <strong>R.layout<\/strong> member, and the layout resources (files) as the members of that folder.<\/p>\n<p>We don&#8217;t have to use the same layout that we used for the initial layout of the widget.  In a more sophisticated widget we might use various layouts according to runtime conditions, but in this case we only need to make one small change to the layout we already declared, which is to change the <strong>Text<\/strong> attribute of the <strong>TextView<\/strong> to the battery level that we wish to display.<\/p>\n<p>A number of methods are provided by the <strong>RemoteViews<\/strong> object for manipulating the views within it.  In this case we are setting the <strong>Text<\/strong> property of a <strong>TextView<\/strong>.<\/p>\n<p>We identify the <strong>TextView<\/strong> in question by reference to the <code>@id+<\/code> id we assigned in the layout &#8211; <strong>lblInfo<\/strong>.  Again, just as with the resources, these ID&#8217;s are created as members of the <strong>R<\/strong> object, this time as members of the <strong>R.id<\/strong> member.<\/p>\n<p>I should explain that I&#8217;m not interested in anything more accurate than whole percentage points, and, on my device at least, the battery level is not reported to any greater level of accuracy anyway (0-100 only), which may be the case on all devices for all I know.  So in this final version I&#8217;ve tweaked the variables and the expression for calculating the <strong>pct<\/strong> value to use integer division.  <\/p>\n<p>The text value we are setting it the string representation of the battery level percentage, with a &#8216;%&#8217; sign appended.<\/p>\n<p>We return this new <strong>RemoteViews<\/strong> object to where the <strong>buildUpdate<\/strong> method was called &#8211; the <strong>onStart<\/strong> method of our service &#8211; which in turn passes it to the <strong>AppWidgetManager<\/strong> which will apply it to our widget UI.<\/p>\n<p>Almost done.<\/p>\n<p>Just one little tweak is needed in the layout to ensure that the text of our widget is visible on both light and dark backgrounds, which is to add a drop-shadow effect by adding the following attributes to the <strong>TextView<\/strong> in the <strong>widgetlayout<\/strong>:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n    android:textColor=&quot;@android:color\/white&quot;\r\n    android:shadowColor=&quot;@android:color\/black&quot;\r\n    android:shadowDx=&quot;2&quot;\r\n    android:shadowDy=&quot;2&quot;\r\n    android:shadowRadius=&quot;2&quot;\r\n<\/pre>\n<figure id=\"attachment_1804\" aria-describedby=\"caption-attachment-1804\" style=\"width: 295px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screenshot_2013-09-30-20-03-27.jpg?ssl=1\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screenshot_2013-09-30-20-03-27.jpg?resize=295%2C200&#038;ssl=1\" alt=\"Night-time...\" width=\"295\" height=\"200\" class=\"size-full wp-image-1804\" data-recalc-dims=\"1\" \/><\/a><figcaption id=\"caption-attachment-1804\" class=\"wp-caption-text\">Night-time&#8230;<\/figcaption><\/figure>\n<figure id=\"attachment_1805\" aria-describedby=\"caption-attachment-1805\" style=\"width: 295px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screenshot_2013-09-30-20-03-46.jpg?ssl=1\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screenshot_2013-09-30-20-03-46.jpg?resize=295%2C200&#038;ssl=1\" alt=\"DAYTIME!\" width=\"295\" height=\"200\" class=\"size-full wp-image-1805\" data-recalc-dims=\"1\" \/><\/a><figcaption id=\"caption-attachment-1805\" class=\"wp-caption-text\">DAYTIME!<\/figcaption><\/figure>\n<p>There we go.<\/p>\n<p>Not perfect but, as with much else with these exercises, it will do for now.  \ud83d\ude42<\/p>\n<p>For those of a curious disposition, here&#8217;s the full source for you to play around with:<\/p>\n<div style=\"width: 80%; border: 1px solid black; background-color: rgb(250,250,255); padding: 5px; margin: 10px auto\">\r\n<p><img src=\"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/plugins\/wp-downloadmanager\/images\/ext\/zip.gif?w=640&#038;ssl=1\" alt=\"\" title=\"\" style=\"vertical-align: middle;\" data-recalc-dims=\"1\" \/>&nbsp;&nbsp;<strong><a href=\"https:\/\/www.deltics.co.nz\/blog\/?dl_name=nz.co.deltics.demo.batterywidget.1.0.zip\">Demo Widget for Android<\/a><\/strong> (38.5 KiB, 578 hits)<\/p>\r\n<div style=\"font: 9pt serif\">Implements a simple battery level monitor home screen widget for Android.<\/div>\r\n<\/div>\n<p>In a real widget I might instead choose to provide the user with some control over the appearance of the widget so that they can adjust it to suit their particular preferences and device wallpaper etc.<\/p>\n<p>I should also implement much more sophisticated battery management.  Since my widget really should only update if the device is already awake, I should listen for notifications from the system telling me when the device enters and leaves sleep state, and use an alarm based update to only update when already awake.<\/p>\n<p>Since I intend using this widget myself, I will be turning my attention to that at some point, but for now, this short series has hopefully added a little more to your knowledge of Android development with Oxygene, as the experience of putting it together has for me.<\/p>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\">[Estimated Reading Time: <\/span> <span class=\"rt-time\">9<\/span> <span class=\"rt-label rt-postfix\">minutes]<\/span><\/span> In the first instalment of this series, I implemented the basic framework of a new appwidget and established a means by which I could debug the widget code. Now it&#8217;s time to add some code worth debugging.<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":[]},"categories":[212,4,180],"tags":[153,224,215,181,223],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1TKYv-sT","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":1873,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1873\/","url_meta":{"origin":1791,"position":0},"title":"Developing an AppWidget &#8211; Part 5","date":"13 Oct 2013","format":false,"excerpt":"In my previous post I explained how I believed I had solved a problem with my widget, only to discover that it created a different problem in the process. I had believed that IntentService based services were long-lived, but in fact this is not the case. However, the change remains\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1774,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1774\/","url_meta":{"origin":1791,"position":1},"title":"Developing and Debugging an AppWidget &#8211; Part 1","date":"29 Sep 2013","format":false,"excerpt":"With my external HDD trials and tribulations behind me, I have finally been able to complete a project I started last weekend - implementing an Android AppWidget. Along the way I have learned some more about both Android and Oxygene and what can be involved with working with the two\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"Adding the xml folder","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Screen-Shot-2013-09-29-at-15.08.09-.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1855,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1855\/","url_meta":{"origin":1791,"position":2},"title":"Developing an AppWidget &#8211; Part 3","date":"08 Oct 2013","format":false,"excerpt":"Well Behaved Widgetry When we left it, my battery widget was working but wasn't particularly well behaved. There was nothing much wrong with the functionality, but plenty wrong with the implementation. Despite their impressive specifications, mobile devices have one very limiting factor. Battery Life. Indeed, the impressive specifications are part\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1869,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1869\/","url_meta":{"origin":1791,"position":3},"title":"Developing an AppWidget &#8211; Part 4","date":"10 Oct 2013","format":false,"excerpt":"Keep On Running... Some may have noticed that I updated my previous post with a footnote describing an issue with my battery widget not resuming it's updates after the phone went into (and came out of) deep sleep. I got to the bottom of that and can now happily report\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1817,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1817\/","url_meta":{"origin":1791,"position":4},"title":"Getting the Battery Level on Android With Delphi","date":"01 Oct 2013","format":false,"excerpt":"Over the past few days I posted a two part series showing how to obtain the current battery level as part of the implementation of an Android AppWidget using Oxygene. As far as I can tell AppWidgets simply aren't possible using Delphi but reading the battery is quite straightforward Android\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1700,"url":"https:\/\/www.deltics.co.nz\/blog\/posts\/1700\/","url_meta":{"origin":1791,"position":5},"title":"Honourable Intentions","date":"22 Sep 2013","format":false,"excerpt":"This is it. The home straight. The final part of my series on writing a camera app using Oxygene for Android. In this concluding part I shall look at making my application a well behaved Android citizen. As well as pointing out (and fixing) some mistakes I have made along\u2026","rel":"","context":"In &quot;Android&quot;","img":{"alt_text":"Post a photo from Google+","src":"https:\/\/i0.wp.com\/www.deltics.co.nz\/blog\/wp-content\/uploads\/Google+-Main-1024x640.jpg?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/1791"}],"collection":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/comments?post=1791"}],"version-history":[{"count":12,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/1791\/revisions"}],"predecessor-version":[{"id":1809,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/posts\/1791\/revisions\/1809"}],"wp:attachment":[{"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/media?parent=1791"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/categories?post=1791"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.deltics.co.nz\/blog\/wp-json\/wp\/v2\/tags?post=1791"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}