Page tree
Skip to end of metadata
Go to start of metadata

This page describes a way to inject a custom Native Plugin (NPI) into the Android and iOS Mobile Application Framework (MAF) Platforms. The NPI is a standalone/self contained part of an application and gives you a way to incorporate your own functionality into your Apps through the MAF Platforms.

Android Native Plug-in Information

Native Plugin Requirement

For the NPI, the following information is needed:

  • Android Library Project packaged into an Android Archive File (AAR).
  • A JSON Configuration file that provides the following (The JSON string will be passed to the Fragment):
    • Fragment Classname (Full Class Name including the package name) of the initial custom Fragment included in the Library Project.
    • Any arguments/parameters that the NPI needs.

 

Example JSON File:

{
  “FragmentClassName”: “com.mobilesmith.rallyconnector.ui.LoginFragment”,
  “rally_url”: “https://rally1.rallydev.com”,
  “company_name”: “MobileSmith”
}

System Frameworks

The Android MAF Platform builds towards the following versions of the Android Platform:

  • Compile SDK Version: 22
  • Build Tools Version 22.0.1
  • Target API Version: 22
  • Minimum SDK Version: 14
  • The builds include the following libraries:
  • Android Support Compat Library v7:22.0.0 - ‘com.android.support:appcompat-v7:22.0.0’
  • Google Play Services Locaion v7.0.0 - ‘com.google.android.gms:play-services-location:7.0.0’
  • Google Play Services Maps v7.0.0 - ‘com.google.android.gms:play-services-maps:7.0.0’
  • Google Play Services Analytics v7.0.0 - ‘com.google.android.gms:play-services-analytics:7.0.0’
  • DiskLRUCache Library v2.0.2 - ‘com.jakewharton:disklrucache:2.0.2’
  • HttpMine v4.2 - ‘org.apache.httpcomponents:httpmime:4.2’
  • Flurry Analytics v3.4.0
  • Google Cloud Messaging Library
  • Picasso Library v 2.5.2 - ‘com.squareup.picasso:picasso:2.5.2’
  • Spring Android v1.0.1
    • ‘org.springframework.android:spring-android-core:1.0.1.RELEASE’
    • ‘org.springframework.android:spring-android-rest-template:1.0.1.RELEASE’
  • Scribe (OAuth Library) v1.3.7 - ‘org.scribe:scribe:1.3.7’
  • GreenRobot EventBus v2.4.0 - ‘de.greenrobot:eventbus:2.4.0’

The NPI must provide any 3rd party libraries in the deployed AAR file.

The MAF builds are currently built towards JDK 1.5.

 

Supported Tools

We support the following tools for NPI development:

  • Android Studio 1.2 Integrated Development Environment
  • Genymotion Android emulators
  • Espresso 2.0 for Automate UI Testing
  • Spoon (1.1.1) for Automated UI Device Testing

Design and Implementation Constraints

Android MAF Platform will provide a Fragment container for 3rd party NPI User Interface elements. These Fragment containers will allow the Platform the ability to embed the NPI’s inside the current UI without changing the underlying code.

Code Guidelines:

  • Anything going against the Play Store guidelines is prohibited in third party code.
  • Exceptions are not handled outside of the custom Fragment: if the custom Fragment does not handle the exception the app will crash.

 

Android Fragments

Android Fragments (from the Android Support Library v4) should be used as a UI Container for NPI’s, it represents a portion of the UI in an Android Activity. This will allow the Android MAF Framework to control most of the screen that has the NPI. The Fragment approach will allow the Custom Native Plugin to have its own lifecycle, receive its own input events, and the ability to swap out its own Fragments without the knowledge of the MAF Platform.

The Android MAF Platform will pass in an Android Bundle to the Fragment that includes the
following:

  • JSON Configuration String (Bundle key = “json_config”) - this will contain the JSON provided in the JSON Configuration File.
  • UI Fragment Container Id (Bundle key = “container_view_id”) - this should be used to replace the current fragment in the Platform:
final FragmentTransaction fragmentTransaction = activity.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(container_view_id, fragment);
if (addToBackStack) {
    fragmentTransaction.addToBackStack(null);
}
fragmentTransaction.commit();

Android Plugin Deployment Information

The Custom Native Plugin should be package in an AAR file with the structure of an Android library as described in the Android Build System Documentation

http://tools.android.com/tech-docs/new-build-system/aar-format

EventBus Library

The Android MAF platform utilizes a publish/subscribe event bus for communications between the platform components. This event bus can be utilized by the NPI for NPI to NPI communication and in the future NPI to MAF/MAF to NPI communication. For more information about the EventBus, see:

https://github.com/greenrobot/EventBus

 

Android Caveats

The following are caveats with Native Plugins on Android:

MapFragments

Map Fragments, used to display Google Maps, are currently not supported in the NPI framework. A workaround is display the map in a WebView.

ActionBar Title

Changing the ActionBar Title is currently not supported in the NPI framework. This functionality will be provided at a later date.

Nested Views

Nested views can cause some latency issues with the NPI’s inside the MobileSmith platform, since the NPI resides several layers deep. See the following App View Hierarchy:

 

iOS Native Plugin Information

The iOS MobileSmith platform primarily works by transitioning to various UIViewController subclasses. One might represent a list of data configured in the MobileSmith website, another might have an e-mail feedback form, etc. This gives applications built in the MobileSmith platform a lot of built-in functionality they could utilize, but sometimes an application has needs for some very specific functionality.

NPIs allow app designers to include a custom UIViewController instance in their application that can be selected and navigated to similar to the other internal UIViewController subclasses. Currently the “scope” of an NPI is limited to what can be accomplished by a UIViewController implementation. An NPI cannot modify the Info.plist file of the app, change the application icon, or modify the Xcode linker flags, for example.

There are two primary components that make up an NPI: a ZIP file that contains all third-party code and resources needed by the device, and a configuration JSON file that is setup in the MobileSmith website with configuration information that could be utilized by the NPI code.

 

iOS NPI Zip File

The zip file has only one required component: a library (.a) file containing the code for the custom UIViewController (or UINavigationController) subclass. In addition it could contain any number of resource bundles or additional library files that are required. If there are multiple items that need to be included in the zip, be sure to select the items in the Finder, right-click and select “Compress # items…” instead of compressing their common parent directory.

NPI Configuration

In the app design UI, the designer can enter in arbitrary key/value pairs to associate with the NPI. This will be converted into a JSON file with a single object and key/value pairs for each field, and the JSON will be provided to the NPI at runtime.

There is only one required key in the configuration JSON for iOS: “ViewControllerClassName.” This is represented by the “iOS Class Name” field in the MobileSmith UI. The value should be a string representing the name of the UIViewController (or UINavigationController) subclass representing the main entry point into the NPI. This JSON is also provided to the UIViewController subclass when it is initialized, so it is possible to have any number of other keys there for the NPI to look for (for example, a server URL). There is only going to be one NPI Configuration JSON that will be used by both Android and IOS NPIs (if both apps are built in the MobileSmith platform).

 

NPI View Controller

The main entry point for an NPI is the main view controller. Whenever the NPI is selected in the MobileSmith application, this is the view controller that will be presented. There are two primary types of NPIs that are supported, depending on their superclass:

  • UIViewController-based NPI. This will typically be added to one of the UINavigationControllers in the MoblieSmith application. The only exception would be if the NPI is included in the tab bar of the application, in which case it will be displayed without any UINavigationController. This is the recommended type of NPI. A UIViewController-based NPI should not override the standard “Back” button in its enclosing UINavigationController.
  • UINavigationController-based NPI: If the NPI view controller is a UINavigationController subclass, then it will typically be presented modally. The only exception would be if the NPI is included in the tab bar of the application. A UINavigationController-based NPI should not be used in the flyout menu, since the flyout hide/show button is part of a MobileSmith navigation controller. A UINavigationController-based NPI is required to implement a “Close” button if needed to dismiss the NPI. A UINavigationController-based NPI should only be used if the NPI needs full control over the navigation controller, or if the NPI is going to be selected from the tab bar and a navigation controller is needed.

 

The view controller class should implement one of the following initialization methods:

  • + (id)npiWithJSON:(NSDictionary *)json; This class method would be appropriate if the NPI is loaded from a UIStoryboard or if some additional logic needed to be done before the NPI knew which UIViewController subclass it wanted to return. It is given the configuration JSON data as an NSDictionary.
  • - (instancetype)initWithJSON:(NSDictionary *)json; This instance method is the most commonly used, and assumes that the NPI is either initialized from a XIB file or entirely in code.

The view controller class could also optionally implement +(void) setupWithJSON:(NSDictionary *)json which will be called on app launch, before the NPI view controller is initialized. This could be useful for downloading additional data that the NPI needs before being displayed.

 

Flyout Menu Integration

If the app designer wants to link an NPI in a flyout menu, then there are a few extra considerations:

The NPI should be a UIViewController-based NPI. It will automatically be added in a UINavigationController that has the flyout toggle button (i.e., a button with a “hamburger” icon).

There are some cases where the NPI coder does not want to be embedded into a MobileSmith UINavigationController. If this is the case, then there is some additional work on the part of the NPI to interact with the application flyout menu:

  • The NPI could use the “btn_flyout” image in the main application bundle, which represents the flyout “hamburger” icon
  • The action to toggle the flyout menu is @selector(toggleFlyoutMenu:). The NPI could either provide a nil target on a control that uses that selector, or use -[UIResponder targetWithAction:withSender:] to determine what object it should send the action to.
  • The JSON configuration provided to the NPI should include a “iOSNavPreference” key with a “never” value to indicate to the MobileSmith code that it should not be placed inside of a navigation controller. Currently this preference is only applicable when the NPI is accessed from the flyout menu, and behavior is undefined if this setting is used in an NPI that is not accessed from the flyout menu.
  • Whenever the user navigates to the NPI to the flyout menu, the MobileSmith code will attempt to instantiate a new instance of the NPI. If this is not desired, the NPI could instantiate itself as a singleton.

 

NPI Bundle

This is optional, and multiple bundles could be provided. All resources (including xib and storyboard files) should be included in this bundle. When creating a new bundle target in Xcode, you need to create a Mac OSX bundle target and then manually change the platform from OSX to iOS. If you are having trouble loading PNG files from the bundle, try removing the COMBINE_HIDPI_IMAGES setting for the bundle target.

Although the bundle target will initially have source code associated with it, the bundles provided for use as a MobileSmith NPI should not have ANY code. You can verify this by examining the bundle and making sure that there is not an executable file in the bundle with the same name as the bundle (e.g., Foo.bundle/Foo).

 

Multiple NPIs

If a single app has multiple NPIs, care should be taken since both NPIs will be linked into the final app. So any shared code should only be defined in one of the NPIs to prevent linker errors.

UIAppearance

MobileSmith utilizes Apple’s UIAppearance protocol for much of its look-and-feel. This automatically sets default colors for some UI elements (e.g., navigation bar background color and text). If no colors are set for these properties in the NPI, then they will automatically get the colors specified for the application on the MobileSmith website. These properties include:

  • UINavigationBar text and background colors
  • UIBarItem text color (iOS 7 only, not iOS 8)
  • UIToolbar text and background color (iOS 7 only, not iOS 8)
  • UISearchBar text and background color

 

Code Requirements

  • NPI library files should be compiled for arm64, armv7, and armv7s architectures. A universal library file (device and simulator) could also be created, but might need to be compiled manually. After generating a device.a and simulator.a library file, a universal version could be created with “lipo –create device.a simulator.a –output universal.a” command in the Terminal.
  • Anything going against the AppStore guidelines is prohibited in third party code.
  • Method swizzling (changing the implementation of an outside class at runtime) is prohibited in third party code.
  • Exceptions are not handled outside of the custom view controller: if it does not handle an exception the app will not handle it and will result in a crash.
  • Currently on iPad only landscape mode and only modal launching of the custom view controller are supported.
  • Currently on iPhone only portrait mode is supported.
  • Swift is not currently supported, since Xcode 6 cannot compile Swift into a static library
  • Pad NPIs cannot currently use UISplitViewControllers
  • NPIs should target iOS 7 and work on iOS 7 and iOS 8
  • Many common filenames are already in use by the core MobileSmith code. NPI filenames and classes should have a common prefix to distinguish itself, e.g. XYZMainViewController.m vs. MainViewController.m
  • If an NPI modally presents a view controller, then it is responsible for dismissing the view controller
  • If the bulk of the NPI is contained in a modally presented view, then the NPI view controller should still contain meaningful content since it is what will be visible once the modal view controller is dismissed.
  • No files or folders contained in the NPI zip should have resource forks attached to them. The xattr command-line tool could be used to verify. (See “File extended resources” section in the appendix)

 

UIAppearance

Below is a listing of system frameworks that we currently link against. If a custom appblock requires a system framework that is not listed here, then we will need to include that framework in our project before we can support that custom appblock:

  • AVFoundation.framework
  • AdSupport.framework
  • AssetsLibrary.framework
  • CFNetwork.framework
  • CoreData.framework
  • CoreGraphics.framework
  • CoreLocation.framework
  • CoreMedia.framework
  • CoreVideo.framework
  • EventKit.framework
  • EventKitUI.framework
  • FacebookSDK.framework
  • Foundation.framework
  • ImageIO.framework
  • MapKit.framework
  • MediaPlayer.framework
  • MessageUI.framework
  • MobileCoreServices.framework
  • PBXFrameworksBuildPhase
  • QuartzCore.framework
  • SenTestingKit.framework
  • SystemConfiguration.framework
  • Twitter.framework
  • UIKit.framework
  • libiconv.dylib
  • libxml2.dylib
  • libz.dylib

 

Below is a listing of system frameworks that we currently link against. If a custom appblock requires a system framework that is not listed here, then we will need to include that framework in our project before we can support that custom appblock:

  • libFlurryAnalytics.a
  • libGoogleAnalytics.a
  • libGoogleConversionTracking.a
  • libzbar.

 

Appendix

iOS Native Plugin Information

One potential issue in an NPI that could cause an app store submission to fail is the existence of extended file resources. These resources cannot always be represented in a zip file, and will sometimes be extracted into a __MACOS directory with individual files for the extended resources. This causes an issue with code signing, since those are seen as separate files that were added after code signing, causing app verifications to fail. To prevent this issue, the contents of an NPI zip file should not contain any extended resources.

To view extended resources, the xattr tool can be used. Before zipping up the NPI, if you navigate in the Terminal to the directory with the static library and/or bundles, execute the following command to recursively list all extended resources for all folders and files in that directory:

find . –exec xattr –l “{}” \;

One of the most common attributes that are accidentally added to files is the com.apple. quarantine attribute. This is typically added to files that are downloaded from an e-mail client or browser and indicate to the Mac operating system that the zip file may contain executable code that has not been approved by the downloader to execute. If you ever download an application and get a pop-up from Apple asking if you are sure you want to launch an application that was downloaded from the internet, that is the work of the com.apple.quarantine attribute. To recursively remove that attribute from all files/folders in the directory, execute the following command in the Terminal:

find . –exec xattr –d com.apple.quarantine “{}” \;

Note that this could show a lot of warning messages when it attempts to remove that attribute from files that do not actually have the attribute, but that is to be expected. After running that command for each unique extended attribute that was found (if any other than com.apple.quarantine are found), run the

find . –exec xattr –l “{}” \;

command again to ensure that all extended attributes are removed, and then zip up the NPI for use in the MobileSmith application.