Skip to content

Instantly share code, notes, and snippets.

@ewieberappc
Last active September 14, 2018 16:36
Show Gist options
  • Save ewieberappc/cd79eb35dc615dd5f118bec6d51de395 to your computer and use it in GitHub Desktop.
Save ewieberappc/cd79eb35dc615dd5f118bec6d51de395 to your computer and use it in GitHub Desktop.
A basic Share Extension Test created by combining two simple test cases. Contains the ShareViewController for the extension and the index controller and view for the Titanium Project
var appGroupId = 'group.com.YourGroupId';
var props = Ti.App.iOS.createUserDefaults({
suiteName: appGroupId
});
var score = props.getInt('score');
if (!score)
score = 1;
props.setInt('score', score);
// Get the shared container path
var sharedPath = Ti.Filesystem.directoryForSuite(appGroupId);
// Copy a file from the application to the shared container
var appFile = Ti.Filesystem.getFile(sharedPath, 'somesharefile.txt');
Ti.API.error(appFile);
function doClick(e) {
score = props.getInt('score');
Ti.API.error("++++++++++ score was: "+score);
score += 1;
props.setInt('score', score);
Ti.API.error("++++++++++ score is: "+props.getInt('score'));
if (appFile.createFile())
appFile.write("Hello");
Ti.API.error("++++++++++ data was: "+appFile.read());
appFile.write($.text.value);
Ti.API.error("++++++++++ data is: "+appFile.read());
}
function getImages(e) {
var dir = Ti.Filesystem.getFile(sharedPath);
var dir_files = dir.getDirectoryListing();
var views = [];
for (var i=0;i<dir_files.length;i++){
if (dir_files[i].indexOf("image") == -1)
continue;
var view = Ti.UI.createImageView({
image: Ti.Filesystem.getFile(sharedPath, dir_files[i])
});
views.push(view);
}
$.scroll.views = views;
}
$.index.open();
<Alloy>
<Window class="container">
<TextField id="text" borderColor="black" top="30%" value="This is from the app" />
<Button onClick="doClick" top="40%">OK</Button>
<Button onClick="getImages" top="50%">Get Images</Button>
<ScrollableView id="scroll" showPagingControl="true" top="60%" height="40%"/>
</Window>
</Alloy>
A basic Share Extension Test created by combining two simple test cases. Contains the ShareViewController for the extension and the index controller and view for the Titanium Project
#import "ShareViewController.h"
@import MobileCoreServices;
static NSString *const AppGroupId = @"group.com.YourGroupId";
static NSString *const AppName = @"YourAppName";
@interface ShareViewController ()
@end
@implementation ShareViewController
NSUInteger m_inputItemCount = 0;
NSString * m_invokeArgs = NULL;
NSUserDefaults *sharedUserDefaults;
NSURL *groupURL;
NSExtensionItem *inputItem;
- (BOOL)isContentValid
{
// Do validation of contentText and/or NSExtensionContext attachments here
return YES;
}
-(void)viewDidLoad
{
// Get and print the Score key from user defaults
sharedUserDefaults = [[NSUserDefaults alloc] initWithSuiteName:AppGroupId];
NSNumber *score = [NSNumber numberWithDouble:[sharedUserDefaults doubleForKey:@"score"]];
NSLog(@"++++++++++ score was: %@", score);
// Read and print the contents of 'somesharefile.txt' in the shared container
groupURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:AppGroupId];
NSString *docPath = [groupURL.path stringByAppendingPathComponent:@"somesharefile.txt"];
NSString *oldData = [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:docPath] encoding:NSUTF8StringEncoding];
NSLog(@"++++++++++ data was: %@", oldData);
}
- (void)didSelectPost
{
// Write and print the contents of 'somesharefile.txt' in the shared container
NSString *docPath = [groupURL.path stringByAppendingPathComponent:@"somesharefile.txt"];
NSString *data = @"I came from the extension";
[data writeToFile:docPath atomically:YES encoding:NSUTF8StringEncoding error:NULL];
data = [[NSString alloc] initWithData:[NSData dataWithContentsOfFile:docPath] encoding:NSUTF8StringEncoding];
NSLog(@"++++++++++ data is: %@", data);
// Check the attachment type
inputItem = self.extensionContext.inputItems.firstObject;
NSItemProvider *urlItemProvider = [[inputItem.userInfo valueForKey:NSExtensionItemAttachmentsKey] objectAtIndex:0];
if ([urlItemProvider hasItemConformingToTypeIdentifier:(__bridge NSString *)kUTTypeURL])
{
// Handle a URL attachment. Write it to user defaults
NSLog(@"++++++++++ Attachment is a URL");
[urlItemProvider loadItemForTypeIdentifier:(__bridge NSString *)kUTTypeURL options:nil completionHandler:^(NSURL *url, NSError *error)
{
if (error)
{
NSLog(@"Error occured");
}
else
{
NSMutableArray *arrSites;
if ([sharedUserDefaults valueForKey:@"SharedExtension"])
arrSites = [sharedUserDefaults valueForKey:@"SharedExtension"];
else
arrSites = [[NSMutableArray alloc] init];
NSDictionary *dictSite = [NSDictionary dictionaryWithObjectsAndKeys:self.contentText, @"Text", url.absoluteString, @"URL",nil];
[arrSites addObject:dictSite];
[sharedUserDefaults setObject:arrSites forKey:@"SharedExtension"];
[sharedUserDefaults synchronize];
}
}];
} else {
NSLog(@"++++++++++ Attachment is not a URL");
[ self passSelectedItemsToApp ];
}
}
- (NSArray *)configurationItems {
// To add configuration options via table cells at the bottom of the sheet, return an array of SLComposeSheetConfigurationItem here.
return @[];
}
- ( void ) addImagePathToArgumentList: ( NSString * ) imagePath
{
assert( NULL != imagePath );
// The list of arguments we will pass to the AIR app when we invoke it.
// It will be a comma-separated list of file paths: /path/to/image1.jpg,/path/to/image2.jpg
if ( NULL == m_invokeArgs )
{
m_invokeArgs = imagePath;
}
else
{
m_invokeArgs = [ NSString stringWithFormat: @"%@,%@", m_invokeArgs, imagePath ];
}
}
- ( NSString * ) saveImageToAppGroupFolder: ( UIImage * ) image
imageIndex: ( int ) imageIndex
{
assert( NULL != image );
NSData * jpegData = UIImageJPEGRepresentation( image, 1.0 );
NSString * documentsPath = groupURL.path;
// Note that we aren't using massively unique names for the files in this example:
NSString * fileName = [ NSString stringWithFormat: @"image%d.jpg", imageIndex ];
NSString * filePath = [ documentsPath stringByAppendingPathComponent: fileName ];
[ jpegData writeToFile: filePath atomically: YES ];
[sharedUserDefaults synchronize];
return filePath;
}
- ( void ) passSelectedItemsToApp
{
NSExtensionItem * item = self.extensionContext.inputItems.firstObject;
// Reset the counter and the argument list for invoking the app:
m_invokeArgs = NULL;
m_inputItemCount = item.attachments.count;
// Iterate through the attached files
for ( NSItemProvider * itemProvider in item.attachments )
{
// Check if we are sharing a Image
if ( [ itemProvider hasItemConformingToTypeIdentifier: ( NSString * ) kUTTypeImage ] )
{
NSLog(@"++++++++++ Attachment is an Image");
// Load it, so we can get the path to it
[ itemProvider loadItemForTypeIdentifier: ( NSString * ) kUTTypeImage
options: NULL
completionHandler: ^ ( UIImage * image, NSError * error )
{
static int itemIdx = 0;
if ( NULL != error )
{
NSLog( @"There was an error retrieving the attachments: %@", error );
return;
}
// The app won't be able to access the images by path directly in the Camera Roll folder,
// so we temporary copy them to a folder which both the extension and the app can access:
NSString * filePath = [ self saveImageToAppGroupFolder: image imageIndex: itemIdx ];
// Now add the path to the list of arguments we'll pass to the app:
[ self addImagePathToArgumentList: filePath ];
// If we have reached the last attachment, it's time to hand control to the app:
if ( ++itemIdx >= m_inputItemCount )
{
[ self invokeApp: m_invokeArgs ];
}
} ];
}
else
{
NSLog(@"++++++++++ Attachment is not an Image");
}
}
}
- ( void ) invokeApp: ( NSString * ) invokeArgs
{
// Prepare the URL request
// this will use the custom url scheme of your app
// and the paths to the photos you want to share:
NSString * urlString = [ NSString stringWithFormat: @"%@://%@", AppName,( NULL == invokeArgs ? @"" : invokeArgs ) ];
NSURL * url = [ NSURL URLWithString: urlString ];
NSString *className = @"UIApplication";
if ( NSClassFromString( className ) )
{
id object = [ NSClassFromString( className ) performSelector: @selector( sharedApplication ) ];
[ object performSelector: @selector( openURL: ) withObject: url ];
}
// Now let the host app know we are done, so that it unblocks its UI:
[ super didSelectPost ];
}
@end
<!-- Replace items in [] -->
<ios>
<team-id>[TEAM ID HERE]</team-id>
<capabilities>
<app-groups>
<group>[group.com.YourGroupId]</group>
</app-groups>
</capabilities>
<extensions>
<extension projectPath="[Path to extension's .xcodeproj]">
<target name="[Target Name]">
<provisioning-profiles>
<device>[Device-UDID]</device>
<dist-appstore/>
<dist-adhoc/>
</provisioning-profiles>
</target>
</extension>
</extensions>
<key>NSExtensionAttributes</key>
<dict>
<key>NSExtensionActivationRule</key>
<dict>
<key>NSExtensionActivationSupportsImageWithMaxCount</key>
<integer>10</integer>
<key>NSExtensionActivationSupportsMovieWithMaxCount</key>
<integer>1</integer>
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
<integer>1</integer>
</dict>
</dict>
<plist>
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>[com.Your.AppId]</string>
</dict>
</array>
</dict>
</plist>
</ios>
@qasim90
Copy link

qasim90 commented Jun 4, 2018

Great. Would have been good if tiapp.xml was included too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment