Feature Highlight - BlackBerry Dynamics Scan Business Card Service

ENTERPRISE / 01.24.20 / BlackBerry

We have a guest post today from Shafer Systems about their shared service.

In this article I want to discuss BlackBerry Dynamics Shared Services.  Shared services are features which are provided to your application from other BlackBerry Dynamics applications.  Shared Services enable Dynamics applications to securely communicate with one another.  This can be as simple as sharing a file with another application, but it can also be as complex as two-way secure communication between applications. 

One benefit of using Shared Services is that an application can utilize functionality already provided by another app without having to recreate it.  In this post, you will be able to develop a small app that demonstrates this process.  You will use the “Scan Business Card” service in order to provide business card scanning features to your application. 

This article should provide you with a basic understanding of the shared services which can be used to add shared functionality to your own application.  To see a list of shared services that are currently available for BlackBerry Dynamics, visit the Shared Services page here: . We encourage you to build your own shared service and share it with the community.

In this sample, you will use two-way communication.  Your application will call “Scan Business Card”.  A provider application will initiate a business card scan and then securely return a v-card file to your application.  When your app is complete the process will look like this:

1) After pressing a button in your application, the card scan begins

2) The Card Scan application recognizes and digitizes the card

3) A v-card with the contact is returned to your application which you can then display to the user or use within your application.

Let’s get started!  To begin, download Notate Pro for BlackBerry, which provides the card scanning functionality. 

In order to get started, request a free trial of Notate Pro to test the service:

Next we will start building the application by modifying an existing Shared Services sample app.  BlackBerry still uses the old name for this, which you will find is called “AppKinetics-SaveEditClient” sample app.  This sample app supports the “SaveEditedFile” service which is a great place for us to begin.  The “SaveEditedFile” service provides a method to return a file back to an application once it has been edited.  In our case, this  will  allow Notate to return a v-card to our application once the business card scanning is complete.

Let’s start by opening the example project, AppKinetics-SaveEditClient.  You can find this, in the location where you installed the BlackBerry SDK.  It should be located under ~/Library/Application Support/BlackBerry/Good.platform/iOS/Examples/objective-c/

You are free to use the swift example instead, but in this post, we will explore the objective-c version.

First make sure that the sample compiles and runs successfully.  You will need to provide your signing development team under BuildSettings in order to get the application to install on a device:

Next it may be helpful to reduce the BlackBerry DynamicsLibrary logging so that you can see only the messages of importance to you:  We can do that by going to the application info, and changing the setting GDConsoleLogger from GDFilterNone to GDFilterAll

Next, make sure that Notate is installed.  This will provide the scanning business card functionality that we are going to use to integrate into your new app.  Run Notate at least once to make sure that the application’s services are registered on the device.

Now let's start working on making your new application.

Start by adding two frameworks to your project for handling contacts.  Go to the application target and select Build phases.  Open the Link Binary with libraries and add two additional libraries, contacts.framework and contactsUI.framework

-(BOOL)scanBusinessCard{ // Specify the service name, version, and method // These definitions can be found here: // NSString * kSSNBScanCardService = @"com.shafersystems.notate.scan-card"; NSString * kSSNBScanCardVersion = @""; NSString * kSSNBScanCardMethod = @"scanCard"; NSString *requestId = nil; NSError * error=nil; //See which applications loaded on the device provide the service that we are interested in NSArray *results = [[GDiOS sharedInstance] getServiceProvidersFor:kSSNBScanCardService andVersion:kSSNBScanCardVersion andServiceType:GDServiceTypeApplication]; //In a real application, we would present the user with a list of installed applications //which provide this service and allow the user to select which application they would //like to handle the operation. However, in this simple example, we will just choose the //first application that shows up in the list. GDServiceProvider * serviceProvider = (GDServiceProvider *)results.firstObject; //Send the scan card request to the provider. It will call us back when a v-card is ready BOOL sendResult = [GDServiceClient sendTo:serviceProvider.address withService:kSSNBScanCardService withVersion:kSSNBScanCardVersion withMethod:kSSNBScanCardMethod withParams:nil withAttachments:nil bringServiceToFront:GDEPreferPeerInForeground requestID:&requestId error:&error]; if (!sendResult) { return NO; } return YES; }

Now let’s change the sample application so that when the user clicks the send button, it will go ahead and issue the scan business card request. 

Open RootViewController.m sendClick: and replace this function with: { //Test the App Kinetics function [self scanBusinessCard]; }

Next, open ServiceController.m GDServiceClientDidFinishSendingTo:

Since we are not sending any files to Notate there is not a need to clean up anything, so delete all of the code in this function after the first log statement.

Now add support for handling the vcards that are returned to us.  GDServiceDidReceiveFrom: is the function that is called when your application registers for a service and is called by another application.  The AppKinetics sample SaveEditClient is already registered to provide the SaveEditedFile service.  If you hadn’t started with a sample, then you would need to register your application in the Markeplace portal to handle the SaveEditedFile service.

In GDServiceDidReceiveFrom: update the line that checks for the file extension.  We will change it from expecting a txt file to expecting a vcf file.  It should look like this now:

// Check file extension if (NSOrderedSame != [fileExtension caseInsensitiveCompare:@"vcf"])

Now, let’s go back to RootViewController and add code to display the imported VCard.

First update the top of the file and import the Contacts libraries that we will use:

#import <Contacts/Contacts.h>

#import <ContactsUI/ContactsUI.h>

Next, change updateFileWithInfo.  This is where the incoming file content is sent. Switch the existing handling of a text file to handle a vcard instead. Comment out the text view loading and replace it with our new VCard handling function:

//self.readOnlyTextView.text = content; [self importVCard:content];

Now let’s write that function:

-(void)importVCard:(NSString *)vcardString{ NSError *errorVCF; NSArray *allContacts = [CNContactVCardSerialization contactsWithData:[vcardString dataUsingEncoding:NSUTF8StringEncoding] error:&errorVCF]; if (!errorVCF) { NSMutableString *results = [[NSMutableString alloc] init]; //NSLog(@"AllContacts: %@", allContacts); for (CNContact *aContact in allContacts) { CNContactViewController *newContactViewController = [CNContactViewController viewControllerForNewContact:aContact]; newContactViewController.delegate = self; newContactViewController.allowsActions = NO; newContactViewController.allowsEditing = NO; UINavigationController *newContactNavViewController = [[UINavigationController alloc] initWithRootViewController:newContactViewController]; newContactNavViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [self presentViewController:newContactNavViewController animated:YES completion:nil]; } NSLog(@"Final: %@", results); } }

Now you just need to set up the RootViewController to act as a delegate for the contacts UI controller.  First, in the header file for RootViewController, specify to support the delegate:


@interface RootViewController : UIViewController Lastly, in RootViewController.m, define the delegate function: -(void)contactViewController:(CNContactViewController *)viewController didCompleteWithContact:(CNContact *)contact{ //Dismiss the view controller [viewController.navigationController dismissViewControllerAnimated:YES completion:nil]; }

That’s it!  Now you should have a working sample app that uses two-way AppKinetics communication to request a business card to be scanned and return a v-card.  You could easily modify this example to provide other functionality such as editing or annotating files and returning them to your application.

Good Luck!


About BlackBerry

BlackBerry is an enterprise software and services company focused on securing and managing IoT endpoints.