Category Archives: code

Theming ListPreference Dialogs on Android Lollipop

ListPreferenceSetting a custom theme color for your Android app is as simple as setting a colorAccent color in the app’s styles.xml file. Yet while this will theme most of the app, oddly ListPreference pop-ups and other dialogs do not naturally inherit the theme used by the rest of the app.

In order to fix this both a dialogTheme and an alertDialogTheme need to be explicitly added to the app’s styles.xml file. The result should look similar to this…

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light">
        <item name="android:colorPrimary">@color/primary
        <item name="android:colorPrimaryDark">@color/accent
        <item name="android:colorAccent">@color/accent
        <item name="android:dialogTheme">@style/DialogStyle
        <item name="android:alertDialogTheme">@style/DialogStyle
    </style>
    <style name="DialogStyle" parent="android:Theme.Material.Light.Dialog">
        <item name="android:colorAccent">@color/accent
    </style>
</resources>

How to treat Android’s up button like a back button

When opening up a child screen on most android apps an arrow will appear on the upper left corner of the screen indicating that you can go back to the previous screen. Android’s documentation refers to this as an “up” button (despite the fact that it clearly points left). While at first glance it appears to similar to the back button it is subtly different.

More complex apps may have a use for the difference in this button’s behavior, but for simple apps the up button acts like a back button that additionally blows away minor state information (such as scroll position) on the parent screen. Fortunately there is a simple way to force the up button to act the same as your standard back button.

In the child activity find the onOptionsItemSelected() method…

public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == android.R.id.home) {
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

and replace NavUtils.navigateUpFromSameTask(this); with finish(); so that your new code now looks like...

public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == android.R.id.home) {
        finish();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Now the back button on your action bar will work just as well as the back button at the bottom of the screen.

Amazon now allowing for fine grained control of BlackBerry app Support

With the Amazon app store coming pre-installed on new BlackBerry 10 phones, Amazon is continuing to improve the support given to developers. Last month Amazon began explicitly adding BlackBerry phones to their testing procedures, and now they are giving developers the option to individually select support for various BlackBerry phones.

amazon

Previously all BlackBerry phones were just included under the generic “all other Android devices” category while a specific per device breakdown like what is now offered was only available for the Amazon Fire line of products.

How to invoke the Classic Camera app

The Classic Camera app can be invoked using the following code…


InvokeManager mInvokeManager = new InvokeManager(this);
connect(mInvokeManager,
      SIGNAL(childCardDone(const
      bb::system::CardDoneMessage&)), this,
      SLOT(childCardDone(const
      bb::system::CardDoneMessage&)));
InvokeRequest request;
request.setAction("bb.action.CAPTURE");
request.setTarget("com.ebscer.classiccamera.card");
request.setMimeType("image/jpeg");
mInvokeManager->invoke(request);

The response data contains the file name of the captured image.

Thoughts on BlackBerry Cascades from 2011

Flipping through an old notebook, I came across my notes on BlackBerry Cascades from BlackBerry DevCon 2011. This was half a year before the framework was released, and a good year and a half before the launch of BlackBerry 10. Since then I have become an expert at Cascades, but it is interesting to see some of my earlier thoughts.IMG_20150311_233508_crop

  • 2D and 3D
  • 90% of UI could be lists
  • QML declarative UI from Qt
  • Asynchronous to help rendering rate
  • Signals to handle events
  • List Types – (SQL,XML,JSON)
  • Uses BBX IDE
  • QML looks nicer than C++
  • Beta in fall (November)
  • Everything in BBX is Qt

Somethings I got right, and with some others I look a little silly. For example Cascades has no support for 3D. In fact Cascades is actively bad at working in three dimensions and doesn’t even support giving z-values to elements. Also the beta wasn’t launched in November (at the time only a month away), but instead the next May. The emphasis on lists was a bit overblown. Creating 90% of an app out of lists can be true for pretty much any framework, and somewhat ironically I don’t actually use a ListView for creating the lists in most of my apps anyhow. The one thing that was apparent to me from the very beginning is that QML is far nicer than C/C++ ever was…

How to get a Slider to stop at discreet points on a Windows Phone app

By default the Slider control that Microsoft provides for Windows Phone Silverlight applications is missing some key properties such as the IsSnapToTickEnabled property. However this can be recreated in code to give Windows Phone apps the same functionality.

First the XAML…

<Slider x:Name="slider" Width="450" ValueChanged="Slider_ValueChanged" Minimum="0" Maximum="10" SmallChange="1"/>

Then in C#…

public void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
        try
        {
            int newValue = (int)e.NewValue;
            slider.Value = newValue;

            //code goes here, using newValue
            //as the slider's value...
        }
        catch (Exception) { }
}

Amazon Appstore testing BlackBerry phones

Below is screen shot of an app acceptance email I received from Amazon. In addition to the many Kindle devices, and the lone “Non-Amazon Android” device, you will find the BlackBerry Classic and the BlackBerry Passport.

IMG_20150206_125743

With the Amazon appstore now preloaded on newer BlackBerry phones, Amazon now appears to explicitly be checking submitted Android apps on these phones. Given the unique screen ratios on these phones, and the fact that they are outselling most of the other devices on this list, it is nice to see Amazon explicitly checking for compatibility. This should free BlackBerry users from having to wonder if anything they download from Amazon will work on their phones.

Creating a Rounded Rectangle in OpenGL

OpenGL is an extremely low level language, and is more or less only capable of drawing triangles. This means that many of the basic shapes that developers are used to having available in a drawing API are not present and must be created from scratch. The below code demonstrates how to draw a rounded rectangle in OpenGL.

static const GLfloat roundRect[] = {
    .92,0,
    .933892,.001215,
    .947362,.004825,
    .96,.010718,
    .971423,.018716,
    .981284,.028577,
    .989282,.04,
    .995175,.052638,
    .998785,.066108,
    1,.08,
    1,.92,
    .998785,.933892,
    .995175,.947362,
    .989282,.96,
    .981284,.971423,
    .971423,.981284,
    .96,.989282,
    .947362,.995175,
    .933892,.998785,
    .92,1,
    .08,1,
    .066108,.998785,
    .052638,.995175,
    .04,.989282,
    .028577,.981284,
    .018716,.971423,
    .010718,.96,
    .004825,.947362,
    .001215,.933892,
    0,.92,
    0,.08,
    .001215,.066108,
    .004825,.052638,
    .010718,.04,
    .018716,.028577,
    .028577,.018716,
    .04,.010718,
    .052638,.004825,
    .066108,.001215,
    .08,0
};

static const GLfloat vbox[] =
{
    0.0f, 0.0f,
    1.0f, 0.0f,
    0.0f, 1.0f,
    1.0f, 1.0f,
};

void render()
{
    setStale(false);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, vbox);
    glPushMatrix();
    glColor4f(0.0f,1.0f,0.0f,1.0f);
    glScalef(.75, .75, 1.0f);
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(2, GL_FLOAT, 0, roundRect);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 40);
    glPopMatrix();
    glDisableClientState(GL_VERTEX_ARRAY);
    setStale(true);
}

Careful observation of the code (especially the line glDrawArrays(GL_TRIANGLE_FAN, 0, 40);) will point out that that technically OpenGL is once again just drawing a collection of 40 triangles in order to create the rounded rectangle shape.

Processing .html files as PHP

In the interest of having cleaner URLs (or simply to maintain existing links) it is often desirable for webpages to end in a .html extension even if they need to be processed as PHP. On Apache servers this is very straight forwards and you just add the following lines of code to your .htaccess file

AddType x-mapp-php5 .php .htm .html

On Windows servers this is slightly more complicated (as are most things). You need the following code in your web.config file and the value for the scriptProcessor is based on the install location of your php-cgi.exe file. Finding the location of this file can often be teased out by looking at the results from the phpinfo(); command.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
		<handlers>
            <add name="PHP_via_FastCG1" path="*.htm" verb="*" modules="FastCgiModule" scriptProcessor="C:\PHP5.5\php-cgi.exe" resourceType="Either" />
            <add name="PHP_via_FastCG2" path="*.html" verb="*" modules="FastCgiModule" scriptProcessor="C:\PHP5.5\php-cgi.exe" resourceType="Either" />
        </handlers>
    </system.webServer>
</configuration>

Creating new projects to optimize BlackBerry 10 apps

Since first releasing the BlackBerry 10 SDK in early 2012, BlackBerry has continued to work on improving their tools. I have recently discovered that significant optimizations are made in newly created Cascades projects. I am currently working on an update to my Stuff I Need app, and have been able to get a 17% reduction in the app’s file size simply by recreating the project from scratch in Momentics. In addition to the smaller install size, the app also appears to be launching quicker. This was done with no changes at all to my code. Using all of the same assets, qml, and c++ files, I created a new project, and then copied my existing files in. The new project contains a few changes to the .pro and the bar-descriptor.xml files, but the majority of the changes seem to be taking place behind the scenes. So for anyone that has been writing BlackBerry Cascades apps for a while now, it may be worth it to recreate your apps and get some free optimizations to your code.

How to get a TextBox in a Windows 8 app to support auto-capitalization

Unlike with most platforms, TextBox controls in Windows 8 metro apps default to a lowercase keyboard instead of assuming that the first word of a sentence should be capitalized. This can be frustrating for users of virtual keyboards who would rather use less keystrokes and let the OS take care of basic formatting. The fix for this is non-obvious, but fortunately quite simple. The solution consists of making sure that spell check is enabled for the TextBox.

This can be done either in XAML with

<TextBox IsSpellCheckEnabled="True" />

or in C# with

TextBox tb = new TextBox();
tb.IsSpellCheckEnabled = true;

How to sideload apps onto WindowsRT devices

With WindowsRT Microsoft has made a bit of an odd platform that only accepts apps from the Windows store and does not provide a simple way to install any custom built apps. The easiest way to sideload an app onto a WindowsRT tablet is to set it up as a developer test device. Unfortunately this does require you to be able to log-in to a Microsoft developer account. Not only is this account not free, but you will be required to reconfirm your credentials every three months. Still this is far easier then the other options to sideload onto WindowsRT.

Step one:

First you need to find the Windows PowerShell app open it using the “Run as administrator” option. Then confirm yes at the UAC prompt. Open the keyboard to type Show-WindowsDeveloperLicenseRegistration and hit enter. Then agree to the prompt, and then log-in to your developer account.

Step two:

In Visual Studio create a Windows Store app in the same manner you would as if you were planning on releasing the app to the store. However once the executable is generated in the AppPackages folder, instead of uploading the .appxupload file find the similarly named test folder and transfer this whole folder onto your WindowsRT device. For WindowsRT devices without support for USB drives this is a challenge all on its own, where the best solution may be to email yourself a .zip file.

Step three:

Now with the folder on your WindowsRT tablet find the Add-AppDevPackage.ps1 file, touch and hold to bring up the right-click menu and select “Run with PowerShell”. Confirm that you do in fact want to open the file, and then follow the multiple prompts within PowerShell. Eventually the app will load be able to run the app as if you had installed it from the app store.

An intro to the Amazon Appstore

As BlackBerry prepares to have the Amazon appstore preinstalled on their phones, I have already had my apps in the Amazon store for two years now.

First of all the best place to have your apps is in BlackBerry AppWorld. If you are writing a native Cascades app, there is no choice except to sell your apps through the BlackBerry store. If you are selling an app based on a cross platform framework such as Cordova or Unity you are better off compiling that code natively to a .bar file as it will run much better then packaging the same code as an Android app. If you have a native Android app, then you are still better off compiling to a .bar file and submitting the app to BlackBerry World. Taking this extra step makes the app easier for users to update and also gives developers the possibility of removing the back bar from apps.

However, simply having the ability to sell to Amazon’s own tablets and phones is enough reason reason to submit your apps into the store.

amazon

For the most part the Amazon store is pretty similar to what all other platforms offer with developers getting a 70% cut of all sales. Payments are made out to developers via direct deposit to a bank account. All apps are submitted as .apk files and like Android apps on BlackBerry, they must not be dependent upon any Google Play services. All apps submitted to the Amazon Appstore require a minimum of three screenshots (at one of a few specific resolutions), and are subjected to a rather comprehensive review policy. App reviews typically take around five days, with rejections usually a case of including a reference to the Google Play store (including something as simple as a link to your other Android apps).

The high praise that BlackBerry has given the Amazon store is mostly marketing fluff. The truth of the matter is that nobody cares about Amazon coins, and this store really isn’t all that different than all of the others…

Adding Cascades highlight colors (without losing the ability to theme 10.2)

PinkWith the release of BlackBerry 10.3 later this year Cascades apps will have the ability to set a custom highlight color. While this is typically defined in the bar-descriptor.xml file, doing so will prevent any theme from being applied when the app is run on phones running an older operating system. Fortunately there is a workaround. (Thanks to Derek Konigsberg for pointing out how to do this).

In short you can override the CASCADES_THEME environmental variable in the brief window between the app being launched, and the creation of the app’s UI. The following code sets a dark theme with pink highlights when run on OS 10.3 and sets a simplier dark theme for older OS versions.

Q_DECL_EXPORT int main(int argc, char **argv)
{
    bb::platform::PlatformInfo p_info;
    QString ver = p_info.osVersion();

    if(ver.startsWith("10.0") || ver.startsWith("10.1") || ver.startsWith("10.2"))
    {
        qputenv("CASCADES_THEME", "dark");
    }
    else
    {
        qputenv("CASCADES_THEME",
            "dark?primaryColor=0xF04FFF");
    }

    Application app(argc, argv);
    MileageTrackerApp mainApp(&app);
    return Application::exec();
}

The recently updated Mileage Tracker app (pictured above) is an example of an app that is using this technique.

Cascades code change in BlackBerry 10.3

There is a slight change in Cascades 10.3 dealing with conditional variables based off of the length of the hint text of a field. For example the following code (designed to only show the TextField when the hint text is not an empty string) would work on BlackBerry 10.2 but fails when run on BlackBerry 10.3

Container
{
    property alias hint:newTextField.hintText
    property alias text:lbl.text
    Label
    {
        id:lbl
        multiline:true
    }
    TextField
    {
        id:newTextField
        visible:
	{
            if(hint.length>0)
            {
                true
            }
            else
            {
                false
            }
        }
    }
}

Fortunately the work around for this is extremely simple. You just need to create (and set) an additional alias for the visibility of the field. This is shown below…

Container
{
    property alias hint:newTextField.hintText
    property alias text:lbl.text
    property alias showTextField:newTextField.visible
    Label
    {
        id:lbl
        multiline:true
    }
    TextField
    {
        id:newTextField
    }
}