About this group

The core value of this group is to bring developers up to speed with BB technology, concentrating on BB10.Exploring efficiency, beauty and power BlackBerry provides to its users by designing Apps that can be used globally and that improves developers life as it improves community life.

Contact Name: Michael Kimathi
E-mail:
  Contact the manager of this GroupSpaces group
Category: Other

News & Announcements

BlackBerry Developer Meet-up September (Built For BlackBerry Revitilized)

  • Saturday, 14th September 2013 at 3:30pm - 8:30pm
    Location: ihub Bishop Magua Building George Padmore Lane Nairobi, Nairobi KE

    Register Here

    • 12 people attended

Built For BlackBerry and Certification

  • Saturday, 3rd August 2013 (all day)
    Location: Ihub 4th Floor Bishop Magua Centre

    Now that everyone is looking forward to build application which qualifies for built for BB We…

    • 45 people attended

TAKE IT TO THE NEXT LEVEL

  • Saturday, 4th May 2013 at 10am - 5:30pm
    Location: IHub Nairobi

    It was amazing to get great ideas hit the floor as we get new developers started as well as…

    • 22 people attended

Previous items

RSS Feed

Now Available: Good SDKs for Android, iOS and Windows

good_logo_608_122

Now Available: Good Dynamics SDKs for Android, iOS and Windows

We are pleased to announce the new release of Good Dynamics SDKs for Android, iOS and Windows.

What’s New

There are multiple new features and improvements that developers will want to check out.

  • Public Key Cryptography support for Kerberos authentication (PKINIT)
  • Certificate Sharing on device
  • Swift 2.0 support
  • Android M suppor
  • Good Dynamics OS X SDK 1.0
  • Support for Android Fingerprint and Samsung Pass authentication
  • New Good Control security policies for fingerprint authentication
  • Xamarin and PhoneGap improvements

Public Key Cryptography support for Kerberos authentication (PKINIT)

PKINIT refers to an authentication mechanism for Kerberos which uses client certificates to authenticate the Good Dynamics(GD) client. PKINIT certificates can be automatically enrolled using a Certificate Authority (CA) server or uploaded in PKCS 12 format to the Good Control (GC). GD apps can take advantage of this authentication mechanism (i.e. no user action required) with a few conditions:

  • Available when the app is using HTTP/S protocol to access resources
  • Supported on Android and iOS platforms
  • Requires Kerberos Constrained Delegation (KCD) not to be enabled
  • Supports only Microsoft CA issued certificates at this time
  • Validated on Windows Server 2008 and 2012

Certificate Sharing on Device

This feature allows GD applications on device to share client certificates. Currently, every GD app has to request and provision their own client certificate when needed, this new feature will allow GD applications to share client certificates and prevent multiple requests to the Certificate Authority(CA). Configuration is not required by IT Admins or developers to take advantage of this feature.  Certificate sharing is automatically enabled for the apps which an Admin has whitelisted in the Certificates > App Usage tab on Good Control.

Adding Support for Swift 2.0 Development on iOS

The followings are available for the Swift development:

  • Good Dynamics APIs in Swift
  • Good Dynamics Swift Template
  • Good Dynamics Swift documentation
  • Support for new Swift features like exceptions, nonull and null handling
  • Good Dynamics Swift sample code

For this release, authentication or redirects are not supported. These features are planned for a future release.

Android M Support

  • Ability to target Android M; Developers can build with target Android M
  • Support for new Android M permission model; Runtime model vs. Install model. GD apps require Android permission READ_PHONE_STATE will need to be granted access
  • Prevent Android M Auto-backup to Google Drive; Prevents the automatic backup of GD application data (ex. Startup file) to Google Drive. All GD files are encrypted with AES-256 which adds an additional level of security

GD OS X SDK 1.0

GD developers can build GD apps supporting the following GD functionalities on Mac OS X:

  • Policies management
  • Compliance enforcement
  • Secure storage
  • Secure communication
  • Kerberos support; this will allow web apps running in Good Access on Mac OS X to use Kerberos authentication to reach protected resources

Fingerprint Authentication

  • Support for Android M and Samsung Pass fingerprint authentication
  • Periodic password request (iOS and Android); Users would be forced to re-enter password at specific intervals when using fingerprint authentication. This feature can be managed by security policies from the GC
  • Fingerprint change detection (iOS and Android); If the device passcode or fingerprint detection is disabled and then re-enabled, the user is forced to enter the GD password to authenticate. This is to prevent a type of attack where an attacker gets possession of an unlocked device, turns off passcode, adds new fingertip and then proceed to use it to unlock a GD app. Additionally for added security when a fingerprint is added or removed or the user is also forced to enter the password to authenticate. This policy is always on thus additional policy setting is not required

Improvements on Xamarin and Cordova(PhoneGap) development tools

We’ve added support for the use of Xamarin to develop GD apps that are explicitly compiled for iOS 9/Xcode 7 SDK. Also for the GD PhoneGap plug-in, we now support all 5.x version of Cordova. The release for Xamarin and PhoneGap are scheduled shortly after the GD SDK release for Android, iOS and Windows.

You can learn more about these releases by accessing the latest release notes, documentation and downloads from the Downloads page in the Good Developer Network.

Stay tuned for our next post!

@echotown


1 day ago
LIVE Enterprise Developer Webcast Series: WatchDox Overview and New Good Dynamics Release

Learn about WatchDox APIs and business use cases and get the latest updates on the new release of Good Dynamics with SDK support for Swift and Mac OS X.

This webcast will cover:

  • WatchDox API & SDK’s – Overview for Developers
    • WatchDox by BlackBerry Enterprise File Sync and Share (EFSS) product is the most secure enterprise file sharing and collaboration solution in the market.
    • In this session we will share a developer overview of the WatchDox API’s including business use cases.
  • An Overview of the New Good Dynamics Release
    • Product Management will provide an update on the upcoming release of Good Dynamics with SDK support for Swift and Mac OS X
    • With Good Dynamics create engaging mobile apps for business users and let the platform take care of all the security, backend, and infrastructure services your apps need
  • New Good Dynamics SDK CODE Snip-it Demo
    • Demo of new Swift 2.0 Good Dynamics APIs in action

 

WatchDox Overview for Developers and New Good Dynamics Release

DATE: June 30, 2016
TIME: 11am ET

Register Now

 


on 24th June
Adding Live Translation to BlackBerry 10 C++ Code

MartinGreen

Editor:  Today we have a guest post from Martin Green.  Martin spent nearly a decade repairing marine navigational equipment on “Lakers” and “Salties”, such as RADAR, Loran C, gyrocompasses, and early SatNav, followed by twenty-five years as a contract Enterprise software developer for governments, banks, and major corporations before coming to mobile and BlackBerry 10 Native development in early 2013. He is the owner of arsMOBILIS and the developer of multiFEED, an RSS/Atom reader app available in BlackBerry World.

If you have built (or are building) your BlackBerry 10 Native Cascades apps with internationalization in mind then you likely have code peppered with QML qsTr() calls and C++ tr() macros. When your app starts up the text wrapped in qsTr() or tr() is substituted with the localized text for the device locale and language (if defined, otherwise default translation is used). This works fine unless you change the language setting on your device while your app is running. Unless you take steps to propagate the language change through your live app, the text displayed in your UI will not match the new device language setting until the page is reloaded or your app is restarted. QML provides for this “live translation” with the Retranslate class which can be used with qsTr() to update translations as soon the device language setting is changed:

Page {
    Container {
        Label {
         id: label01

         // ---This label's text will be live translated
         text: qsTr("Label 1") + Retranslate.onLanguageChanged
      }
      Label {
         id: label02

         // ---This label's text will be static translated
         text: qsTr("Label 2")
      }
   }
}

In this example label01 will have its text attribute live translated so that it is updated as soon as the device language is changed. On the other hand label02 will only have its text translated when the app is first started and subsequent language changes while the app is running will not update it.

Using the Retranslate class with QML makes live translation as simple as adding a small amount of code right after every use of qsTr(), but C++ provides no such convenience. To implement live translation in C++ code it is necessary to call the setXXX() slot for a string attribute with the tr() macro once to do the initial translation then connect the setXXX() slot to a LocaleHandler instance which emits a signal every time the language (or locale) changes. This is complicated by the fact that the LocaleHandler knows that the language has changed, but it doesn’t know which text key to supply to the slots it is attached to so we have to attach the LocaleHandler signal to an intermediary slot which knows what translation key to use for that attribute and which then emits another signal with the key as a parameter which must be connected to the control setXXX() slot. This means that for every single control attribute you want to live translate you will need a separate intermediary slot defined somewhere, a related signal for that slot with a QString argument, and two QObject::connect() calls. For every attribute we want to live translate. Obviously this gets very ugly, very fast.

I prefer to use C++ with little or no QML to lay out my app pages so I was determined to find a solution which was as easy to use as Retranslate in QML (or nearly so) and after some trial and error I came up with a solution I’m very happy with, which I called LiveTranslator. The core of this technique is a new C++ class called LiveTranslator. The usage syntax is a little more complicated than using QML Retranslate, but like Retranslate you only need to add one line of code for each attribute you want live translation on. Here is the header for LiveTranslator:

#ifndef LIVETRANSLATOR_HPP_
#define LIVETRANSLATOR_HPP_

#include <bb/cascades/LocaleHandler>

using namespace bb::cascades;

class LiveTranslator: public QObject {
    Q_OBJECT

    QString _key;
    QString _context;

    static LocaleHandler* _localeHandler;

public:
    LiveTranslator( const QString& context,
            const QString& key,
            QObject* target,
            const char* slot );

    static void setLocaleHandler( LocaleHandler* localeHandler );

private slots:
    void localeOrLanguageChangedHandler();

signals:
    void translate( const QString& string );
};

#endif /* LIVETRANSLATOR_HPP_ */

…and the body…

#include "LiveTranslator.hpp"

/* ---Initialize the locale handler pointer on app startup so we can tell if it
has been set properly later */
LocaleHandler* LiveTranslator::_localeHandler = 0;

/* ---Note that the target control is also used as the parent so the live translator dies when the control does */
LiveTranslator::LiveTranslator( const QString& context,
        const QString& key,
        QObject* target,
        const char* slot ) :  QObject( target ) {

    bool success;
    Q_UNUSED( success );

    // ---Save the context and key string
    this->_key = key;
    this->_context = context;

    // ---Die (during debug) if locale handler wasn't set properly before use
    Q_ASSERT( LiveTranslator::_localeHandler );

    // ---Watch for locale or language changes
    success = QObject::connect(
        LiveTranslator::_localeHandler,
        SIGNAL( localeOrLanguageChanged() ),
        SLOT( localeOrLanguageChangedHandler() )
    );
    Q_ASSERT( success );

    // ---Trigger specified slot when locale or language changes
    success = QObject::connect(
        this,
        SIGNAL( translate( const QString& ) ),
        target,
        slot
    );
    Q_ASSERT( success );
}

void LiveTranslator::localeOrLanguageChangedHandler() {
    /* ---Use the specified slot on the target to update the appropriate string
    attribute with the translated key */
    emit translate(
        QCoreApplication::translate(
            this->_context.toLocal8Bit().constData(),
            this->_key.toLocal8Bit().constData()
        )
    );
}

/* ---This function MUST be called once with a valid LocaleHandler before any
LiveTranslator classes are instantiated */
void LiveTranslator::setLocaleHandler( LocaleHandler* localeHandler ) {
    LiveTranslator::_localeHandler = localeHandler;
}

LiveTranslator encapsulates all the ugly stuff, including remembering the translation key, the intermediary slot/signal, and all signal/slot connections necessary for live translation. Using it is as simple as creating an instance of LiveTranslator, passing the constructor the translation key for the attribute (and the context, but more on that later), the target UI control, and the slot on that component that will accept the updated translation. Note that tr() only works with static key strings…

// ---This is valid
QString str1 = tr("string one");

// ---This is not!
Qstring str1 = "string one";
QString str2 = tr(str1);

…so rather than tr(), LiveTranslator must use QCoreApplication::translate() internally.

An example of LiveTranslator usage:

MyClass::MyClass() {
    Label* label = Label::create().text( tr("Label one") );
    new LiveTranslator( "MyClass", "Label one", label,
        SLOT(setText(const QString&)) );
    
    Option* option = Option::create().text( tr("Option one") )
        .description( tr("Option one description") );
    new LiveTranslator( "MyClass", "Option one", option,
        SLOT(setText(const QString&)));
    new LiveTranslator( "MyClass", "Option one description", option,
        SLOT(setDescription(const QString&)));
    
    ActionItem* actionItem = Option::create().title( tr("Action one") );
    new LiveTranslator( "MyClass", "Action one",
        actionItem, SLOT(setTitle(const QString&)));
}

Note that there is no need to save a reference to the new LiveTranslator instance since the constructor sets the “target” control as the parent. When the control is destroyed by your app the LiveTranslator will go with it. Also note that Momentics doesn’t know anything about LiveTranslator so you won’t be warned in the editor if the slot you provide is not valid. There is a Q_ASSERT in LiveTranslator though so you will know if the connection failed when testing your app in Debug mode.

The first parameter for the LiveTranslator constructor is the “context” where the translation key is located. When you use the tr() macro (or QML qsTr() function) the code parser makes note of where it found the key and stores it in the translation file along with the key. This way you could use the same translation key on different pages, and if the context is different you could have them translated differently. Again, the Index parser doesn’t know anything about the LiveTranslator class though so you have to tell it the context explicitly. For C++ the context is always the name of the class containing the code you are translating. Also, in case it isn’t obvious, the “key” parameter must be the same value as the one used with tr() on the line before it.

There is one thing you must do before using LiveTranslator in your C++ code and that is to give it a LocaleHandler to work with. Rather than force you to pass a LocaleHandler to every instance of LiveTranslator, you tell LiveTranslator which one to use just once with a static function call. If you created your app from one of the Momentics templates then you already have a handler you can use:

#include “LiveTranslator.hpp”

ApplicationUI::ApplicationUI() : QObject() {
    // prepare the localization
    m_pTranslator = new QTranslator( this );
    m_pLocaleHandler = new LocaleHandler( this );
    
    // Use this locale handler for all the live translations too
    LiveTranslator::setLocaleHandler( m_pLocaleHandler );

    ...
    ...
    ...
}

If all you care about live translating are normal UI components, then you have all you need now to easily implement live translation in your C++ code. If, however, you also want to have LiveTranslator work with certain system controls, such as SystemUiButton or SystemDialog you have a little more work ahead of you. The problem is that on these classes the attributes we would want to live translate are set with functions, not slots. This means that there is no way to tell LiveTranslator how to update the desired strings since it only works with Qt slots. The solution is quite simple though, all we need is to define a “helper” class for each system component type which can provide access to the setting function via slots. Here is a helper class for SystemUiButton

/*
 * SystemUIButtonTrxHlp.hpp
 *
 */

#ifndef SYSTEMUIBUTTONTRXHLP_HPP_
#define SYSTEMUIBUTTONTRXHLP_HPP_

#include <bb/system/SystemUiButton>

using namespace bb::system;

class SystemUiButtonTrxHlp: public QObject {
    Q_OBJECT

    SystemUiButton* _button;
public:
    SystemUiButtonTrxHlp( SystemUiButton* button );

public slots:
    void setLabel( const QString& label );
};

#endif /* SYSTEMUIBUTTONTRXHLP_HPP_ */

/*
 * SystemUiButtonTrxHlp.cpp
 *
*/

#include "SystemUiButtonTrxHlp.hpp"

SystemUiButtonTrxHlp::SystemUiButtonTrxHlp( SystemUiButton* button ) :
        QObject( button ) {
    this->_button = button;
}

void SystemUiButtonTrxHlp::setLabel( const QString& label ) {
    this->_button->setLabel( label );
       }

As with LiveTranslator the constructor automatically makes the target button the parent, so you can create an instance of the helper and forget it. Now a similar helper for SystemDialog

/*
 * SystemDialogTrxHlp.hpp
 *
*/

#ifndef SYSTEMDIALOGTRXHLP_HPP_
#define SYSTEMDIALOGTRXHLP_HPP_

#include <bb/system/SystemDialog>

using namespace bb::system;

class SystemDialogTrxHlp : public QObject {
    Q_OBJECT

    SystemDialog* _dialog;

public:
    SystemDialogTrxHlp( SystemDialog* dialog );

public slots:
    void setBody( const QString& text );
    void setRememberMeText( const QString& text );
    void setTitle( const QString& title );
};

#endif /* SYSTEMDIALOGTRXHLP_HPP_ */

/*
 * SystemDialogTrxHlp.cpp
 *
*/

#include "SystemDialogTrxHlp.hpp"

SystemDialogTrxHlp::SystemDialogTrxHlp( SystemDialog* dialog ) :
        QObject( dialog ) {
    this->_dialog = dialog;
}

void SystemDialogTrxHlp::setBody( const QString& title ) {
    this->_dialog->setBody( title );
}

void SystemDialogTrxHlp::setRememberMeText( const QString& text ) {
    this->_dialog->setRememberMeText( text );
}

void SystemDialogTrxHlp::setTitle( const QString& title ) {
    this->_dialog->setTitle( title );
}

Now let’s create a SystemDialog with live translation…

#include “SystemDialogTrxHlp.hpp”
#include “SystemUiButtonTrxHlp.hpp”

using namespace bb::system;

void MyClass::openDialog() {
    SystemDialog* dialog = new SystemDialog( tr(“Confirm Button”),
        tr(“Cancel Button”) );
    dialog->setTitle( tr(“Dialog Title”) );
    dialog->setBody( tr(“”Dialog Body”) );

    // ---Enable live translation
    new LiveTranslator( “MyClass”, “Dialog Title”, new SystemDialogTrxHlp( dialog ),
        SLOT(setTitle(const QString&)) );
    new LiveTranslator( “MyClass”, “Dialog Body”, new SystemDialogTrxHlp( dialog ),
        SLOT(setBody(const QString&)) );
    new LiveTranslator( “MyClass”, “Confirm Button”,
        new SystemUiButtonTrxHlp( dialog->confirmButton() ),
        SLOT(setLabel(const QString&)) );
    new LiveTranslator( “MyClass”, “Cancel Button”,
        new SystemUiButtonTrxHlp( dialog->cancelButton() ),
        SLOT(setLabel(const QString&)) );

    // ---Now for the magic ingredient
    bool success = QObject::connect( LiveTranslator::localeHandler(),
        SIGNAL(localeOrLanguageChanged()), dialog, SLOT(update()) );
    Q_UNUSED(success);
    Q_ASSERT(success);
}

Now for the bad news. See those few lines at the end of the function after the “magic ingredient” comment? Without them live translation of SystemDialog won’t work. Unlike regular UI components, SystemDialog and its brethren don’t automatically repaint themselves or their children when you change one of their attributes. Instead you make all the changes you want and then call or trigger the update() slot. The bad news? That function wasn’t added until the 10.2 API. This means that full live translation of system dialogs is not possible below that API level. I say “full” live translation because even with 10.0 and 10.1 if you leave SystemUiButton labels at their defaults or set them to one of the values that Cascades natively knows how to translate then those labels will be live translated with no additional effort by you. For instance, if you set the SystemDialog confirm button to read “Ok” or “Confirm” then Cascades will automatically add live translation of those words into any language you change your device to and you don’t even need to use the tr() macro when setting them. By carefully choosing your dialog title and body you might be able to get most of the way to live translation even with the lower API levels. Unfortunately, I don’t know of a list of button labels that Cascades can live translate natively so you might need a bit of trial and error. If there is any good news in this it’s that unlike regular screen elements, dialogs are transient entities so the lack of live translation is only evident for a moment. The next time your user opens a dialog, even the same one, it will be correctly translated into the new language.

I have provided the source files for LiveTranslator and some helper classes so all you need to do to get live translation working in your BlackBerry 10 Native C++ code is grab LiveTranslator from github and add it to your project (and any helpers you need too), add a call to LiveTranslator::setLocaleHandler() at the beginning of your main app class constructor and then call new LiveTranslator(…) with the appropriate parameters for each control attribute you want to be live translated. I leave it to the reader to create any additional helper classes they might need. I also created an example app that you can download and run without coding anything yourself. Note that this demo app includes code that live translates a SystemDialog so you must compile it with API 10.2 or better.

The Retranslate class makes it easy to perform live translations from QML, but Cascades does not provide a similar tool for C++ code. A few lightweight classes and extra lines of code bring similar functionality to C++, and best of all you don’t have to rewrite your app to take advantage of it. Just add one line of code for each UI component attribute you want to translate and the LiveTranslate class will take care of the rest.


on 21st June

Create a site like this for your own group.
Take a Tour or Sign Up

Members

Events

July 2016
 
« »
Mon Tue Wed Thu Fri Sat Sun
27 28 29 30 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31

BlackBerry Enterprise Developers Kenya

Powered by GroupSpaces · Terms · Privacy Policy · Cookie Use · Create Your Own Group