Child pages
  • iPhone Plugin Guide
Skip to end of metadata
Go to start of metadata

Downloads

The RAMP iOS template project for Xcode can be downloaded here.

All iOS plugins, including the example plugin, are available here.

All the resources required to build an iOS plugin are provided as an Objective-C framework. The framework, rampvm.framework, is available here.

Introduction

It is explained in the iPhone Building Guide that an iPhone RAMP app cannot be deployed through the usual channels. This is also true for developing a plugin and implementing it in an iPhone RAMP app.

The plugin process is more or less similar to the explanation in the RAMP VM Plugins document. The big difference is that the RAMP Deployment platform is not involved and its role has to be performed manually. This guide references the RAMP VM Plugins document and assumes you are familiar with it.

Writing a Plugin

Note the classes that need to be extended and implemented are now provided in Objective-C and look slightly different to their Java versions.

Writing a function plugin

The differences in Objective-C's version of class APluginFunction:

  • Instead of two possible constructors, there are now two possible initialization methods: initWithName that takes a single string and initWithNames that takes an array of strings.
  • The invoke method now also takes a NSError object as an extra, third parameter.
  • An added, useful method is currentViewController that retrieves the ViewController that is currently active in the RAMP app. Launching a new ViewController from a plugin requires access to the currently active one.

The APluginFunction's header file is given below:

ApluginFunction.h
#import <Foundation/Foundation.h>
#import "NativeFunction.h"

@interface APluginFunction : NSObject <NativeFunction> {
	NSArray* names;
}

+(UIViewController*) currentViewController;

// Register function names
-(id) initWithName:(NSString*)aName;
-(id) initWithNames:(NSArray*)theNames;

-(NSArray* const) getNames;

-(id const) invoke:(NSString*)functionName params:(NSDictionary*)params error:(NSError**)error;

// The abstract methods:
-(id) invoke:(NSString*)functionName args:(NSArray*)args error:(NSError**)error;
-(BOOL) isSupported;
	
@end

Remember

All the resources required to build an iPhone plugin are provided as an Objective-C framework. The framework, rampvm.framework, is available here.

An iPhone example is given with the code below. It is the iPhone version of the SMS Plugin example. This plugin provides the RAMP-script function vmt_sendSms(number, message).

SMSPlugin.h
#import <Foundation/Foundation.h>
#import <MessageUI/MessageUI.h>
#import "APluginFunction.h"

@interface SMSPlugin : APluginFunction <MFMessageComposeViewControllerDelegate> {
}

- (id) invoke:(NSString*)functionName args:(NSArray*)args error:(NSError**)error;
- (BOOL) isSupported;

@end
SMSPlugin.m
#import "SMSPlugin.h"

@implementation SMSPlugin


- (SMSPlugin*) init
{
	[self initWithName:@"vmt_sendSms"];
	return self;
}


- (BOOL)isSupported
{
	return [MFMessageComposeViewController canSendText];
}


- (id) invoke:(NSString*)functionName args:(NSArray*)args error:(NSError**)error;
{
	NSString* response = @"1";
	
	if (![functionName isEqualToString:@"vmt_sendSms"])
		response = @"unknown function";
	
	else if ([args count] < 2)
		response = @"parameters missing";
	
	else if (![self isSupported])
		response = @"function not supported";
	
	else
	{
		NSString* number = [args objectAtIndex:0];
		NSString* message = [args objectAtIndex:1];
		
		MFMessageComposeViewController* controller = [[MFMessageComposeViewController alloc] init];
		controller.messageComposeDelegate = self;
		
		controller.body = message;
		controller.recipients = [NSArray arrayWithObjects:number, nil];
		
		[[APluginFunction currentViewController] presentModalViewController:controller animated:YES];
		[controller release];
	}
	
	return response;
}


- (void) messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
	NSString* message = nil;
	switch (result) 
	{
		case MessageComposeResultCancelled:
			message = @"Cancelled";
			break;
			
		case MessageComposeResultFailed:
			message = @"Unknown Error";
			break;
			
		case MessageComposeResultSent:
			message = @"Success";
			break;
			
		default:
			break;
	}
	
	if (message != nil)
	{
		UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"SMS Sending"
							message:message
							delegate:self 
							cancelButtonTitle:@"OK" 
							otherButtonTitles: nil];
		[alert show];
		[alert release];
	}

	[[APluginFunction currentViewController] dismissModalViewControllerAnimated:YES];
}

@end

Note the following in the example code:

  • Registering the function name in the init method.
  • The isSupported method checking if the plugin is supported on the device.
  • The use of currentViewController method to launch and dismiss a new viewController.

Writing a UI Component plugin

The interface (protocol) class APluginUi is basically identical to its Java version.

Including Plugins in an App

Note

All iOS plugins, including the example plugin, are available here.

To include one or more plugins in an app,

  1. the plugins must be included in the RAMP iPhone template project that will build the app and
  2. the VM must be aware of the plugins' existence.

A plugin can either be included as source code or in a compiled form. The template project contains a plugins directory in its root with sub-directories headerslibraries and resources specially created for keeping plugins. The template project is configured to search the plugins' headers directory for header files. Libraries and other resource files (e.g. images) must be included manually using Xcode in the target named "vmt" (there is only one target).

Note

The rampvm.framework framework is already included in the template project.

The file plugins.txt is provided in the root of the template project to inform the VM of the plugins' existence. For all the plugins that you wish to include in an app, the name of the plugin's class (i.e. the class that extends class APluginFunction) must be included in plugins.txt. The names must be listed vertically in Plugins.txt, one below the other. The following is the plugins.txt file for the guide's function plugin example.

plugins.txt
  
SMSPlugin

Using a Plugin's Function in an App

Note

UI Component plugins require no further configuration to use.

The final hurdle is persuading the RAMP IDE to allow the use of a function plugin's function. This is typically achieved with the "Get RAMP VM plugins..." option in the IDE, but without the development platform's involvement it has to be done manually.

In the root directory of a RAMP project (not the RAMP VM template project) there is a file .plugins. This file is typically hidden in most operating systems and can be created if it does not exist. This file contains a list of all the plugin functions that a project allows. The function names appear as they are to be used in the IDE, but without any reference to their parameters. The names are listed one below the other (similar to plugins.txt). This file should be edited and all required plugin functions included. The following is the .plugins file for the guide's function plugin example:

.plugins
  
vmt_SendSms

Note

If new plugin functions are not recognized after editing .plugins, restart Eclipse.

 

Appendix I - Standard PluginUtils methods on iOS

(void) executeAction: (NSString*) action

Execute a RAMP action where an action is either

  • a RAMP function
  • or going to a ramp form.

 

An example of a RAMP function:

[[PluginUtils getInstance] executeAction:@"login('username', 'password')"];

is equivalent to RAMP code

 login("username", "password");

 

An example of going to a RAMP form:

 [[PluginUtils getInstance] executeAction:@"form1"];

equivalent to RAMP code

 goto("form1");

 

(void) executeFunction: (NSString*) function withArgs: (NSArray*) args

Execute a RAMP function, e.g.   

[[PluginUtils getInstance] executeFunction:@"login" withArgs:[NSArray arrayWithObjects: @"username", @"password", nil]]

is equivalent to RAMP code

login("username", "password");

 

(NSString*) getTrimmedKey: (NSString*) key node: (id<IDotNode>) node

Given a node and key, it returns the key trimmed (truncated) to everything after the node's ID. Used when developing UI components.

 

(id) getValueFromUxmlChildren: (NSArray*) nodes parent: (id<IDotNode>) parent key: (NSString*) key

For parent component with an array of nodes as its children, returns the value for the first IDotNode instance in nodes that supports the given key.

 

(BOOL) setValue: (id) value forKey: (NSString*) key inUxmlChildren: (NSArray*) nodes parent: (id<IDotNode>) parent

For parent component with an array of nodes as its children, set the value for the first IDotNode instance in nodes that supports the given key. Returns true if successful.

 

(NSMutableArray*) unmarshall:(NSArray*)marshalled unmarshalled:(NSMutableArray*)unmarshalled

Unmarshalls an array of marshalled (raw) UXML components.

 

(NSMutableDictionary*) marshall:(id <IDotNode>)node attributes:(NSArray*) attributes

Marshall (convert to raw type) a UXML node that support all the keys listed in the attributes parameter.

 

(NSMutableArray*) marshallChildren:(NSArray*) childNodes

Marshall (convert to a list of raw types) a vector of UXML nodes.

 

(UxmlStyle*) getUxmlStyle: (NSString*) styleName

Retrieve the UXML style object that has ID styleName.

Appendix II - PluginUtils methods unique to iOS.

(void) executeAction: (NSString*) action viaUxmlComponent:(id <IDotNode>)srcComponent

execute a RAMP action and inform the VM that a specific IDotNode UI component triggered the action.

 

(CGSize) getAppDisplaySize

 Returns the display size of the device.

 

(AppOrientation) getAppOrientation

Returns the device's orientation

 

(Image*) getImage: (NSString*) imageName

Returns the Image object for the Uxml Image Component that has ID imageName.

 

(UIViewController*) getCurrentViewController

Returns the currently displayed VM UIViewController.

 

(void) setCurrentViewController:(UIViewController*) viewController

Set the currently displayed VM UIViewController. Only for testing purposes.

 

(BOOL) isRetinaDisplay

Returns true if device has a retina display.

 

(BOOL) isIPad

Returns true if device is an iPad

 

(BOOL) isIosVersionGreaterOrEqual:(NSString*) version

Returns true if device's iOS version is greater or equal to the version parameter.

 

(void) displayFatalError: (NSString*) message

Go to the RAMP VM's fatal error page and display the message parameter.

 

(void) runOnUIThread:(void ( ^ )())block

Run a block on the UI thread.

 

(void) runOnBackgroundThread:(void ( ^ )())block

Run a block on a backgroud (non-UI) thread.

 

(void) runBlock:(void (^)())block

Run a block.

 

(NSNumber*) parseNumber:(NSString*)value error:(NSError**) error

 Convert RAMP's string value to a Objective-C NSNumber.

 

(NSNumber*) parseNumber:(NSString*)value isFloat:(BOOL*)isFloat error:(NSError**) error

Convert RAMP's string value to a Objective-C NSNumber and detect if number is a float.

 

(UIColor*) getUIColorWithDescriptor:(long long) d

Convert a long representation of a color to a UIColor object.

  • No labels