Passing custom parameters to Phonegap plugin - ios

I have written a Phonegap plugin in order to integrate my Phonegap application with a native SDK library. In order to pass some device registration information to the native library I have used an Objective-C category to plug my own handler after didFinishLaunchingWithOptions, pretty much the same way the Phonegap Push Plugin does. I therefore have something like the following:
#implementation AppDelegate (MyLib)
// Using method swizzling to plug our own init method which allows us to
// add our own listener for the didFinishLaunching event without overwriting
// the one already defined by Phonegap.
+ (void)load
{
Method original, swizzled;
original = class_getInstanceMethod(self, #selector(init));
swizzled = class_getInstanceMethod(self, #selector(swizzled_init));
method_exchangeImplementations(original, swizzled);
}
- (AppDelegate *)swizzled_init
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(launchHandler:)
name:#"UIApplicationDidFinishLaunchingNotification" object:nil];
// This actually calls the original init method over in AppDelegate.
return [self swizzled_init];
}
// This code will be called immediately after application:didFinishLaunchingWithOptions:.
- (void)launchHandler:(NSNotification *)notification
{
NSString* apiKey = #"xxxxx";
// Do some initialisation and register the device using the apiKey
}
#end
The apiKey is specific to my application and right now it is defined in AppDelegate+MyLib.m as shown in the code above. My question is, is there a way to allow my Phonegap app to customise this when importing the plugin? Could it be defined in my app's config.xml (or in any other place if that makes a difference) and somehow passed to the plugin's AppDelegate as a parameter?

Firts of all, you don't need to use swizzling, just read how to get the UIApplicationDidFinishLaunchingNotification from a CDVPlugin subclass
Customizing iOS's application:didFinishLaunchingWithOptions: method in a Cordova/Ionic project
Now you can use the preference tag on the config.xml
<preference name="apiKey" value="yourApiKeyHere" />
Then, you get the "apiKey" on your code (on a CDVPlugin subclass) doing this:
NSString* apiKey = [self.commandDelegate.settings objectForKey:[#"apiKey" lowercaseString]];

Related

How to call methods in the custom view in iOS module, from titanium project?

I need to call methods in the custom view in iOS module from titanium project. I have followed the tutorials in Appcelarator documentation about creating iOS module. I could create the custom view in Titanium using below code.
var manage = require('com.test');
var manageView = manage.createView({
left:40,
right:40,
top:40,
height: 250,
backgroundColor:'blue' }); manageView.customMethodInView();
But i got error like "customMethodInView is not a function" when i run the app.
#import "TiViewProxy.h"
#import "CustomView.h"
#interface ComTestViewProxy : TiViewProxy {
CustomView *customView;
}
- (void) customMethodInView;
#end
This is the code in viewProxy class in iOS Module project.
Please help.
I know this is late, but for any wondering soul out there, it is my understanding that even if you don't intend to pass an argument for your method, the signature of the method in the native module should always take one:
your method
- (void) customMethodInView;
should look like this :
- (void)customMethodInView:(id)unused;

iOS - How does Cordova invoke objective c function?

How does cordova trigger objective-c native method. For example- When a user taps on submit button (html button), app needs to invoke native objective c function called 'dataSubmitted'.
Does Cordova monitor webview navigation and based on URL tags call method internally?
Is there any way JavaScript can interact with Obj-c native methods except monitoring webview navigations?
There are two ways to communicate with native language from JS.
1. Go to MainViewController.m -> find a function named webViewDidFinishLoad
and add the follwing code snippet..
- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{
NSString *pageUrl = [theWebView.request.URL absoluteString];
if ([pageUrl containsString:#"xyz"]) {
// xyz for xyz.html
}else if ([pageUrl containsString:#"abc"]) {
// abc for abc.html
}
self.webView = theWebView;
return [super webViewDidFinishLoad:theWebView];
}
Develop your own native plugin with cordova.exec ;
There are a few libraries available to communicate between Javascript and Objective-C it seems:
WebViewJavascriptBridge: https://github.com/marcuswestin/WebViewJavascriptBridge
GAJavaScript: https://github.com/newyankeecodeshop/GAJavaScript
I suggest you to check out this beautiful SO Post which explains Javascript & Objective-C interactions in detail.

Possible to bring the app from background to foreground?

When running an XCT UI test it is possible to put the application under test in the background with:
XCUIDevice().pressButton(XCUIDeviceButton.Home)
It it possible in some way to bring the app back to foreground (active state) without relaunching the application?
Update for Xcode 9: Starting in Xcode 9, you can now simply call activate() on any XCUIApplication.
let myApp = XCUIApplication()
myApp.activate() // bring to foreground
https://developer.apple.com/documentation/xctest/xcuiapplication/2873317-activate
Yes, it is. But, you'll need XCUIElement's private headers (which are available via header dump from Facebook here). In order to foreground the app, you need to call resolve which I believe resolves the element's query (which for applications means foregrounding the app).
For Swift, you'll have to import the XCUIElement.h into your bridging header. For Objective-C you'll just need to import XCUIElement.h.
With the app backgrounded:
Swift:
XCUIApplication().resolve()
Objective-C
[[XCUIApplication new] resolve];
If this is the only functionality you need, you could just write a quick ObjC category.
#interface XCUIElement (Tests)
- (void) resolve;
#end
If you need to launch / resolve another app. Facebook has an example of that here by going through the Springboard.
As of Xcode 8.3 and iOS 10.3, you can accomplish this with Siri:
XCUIDevice.shared().press(XCUIDeviceButton.home)
XCUIDevice.shared().siriService.activate(voiceRecognitionText: "Open {appName}")
Include #available(iOS 10.3, *) at the top of your test suite file and you should be good to go!
This is what I have in my XCUITest and it works like a charm (xcode 10.1 and test device is iPhone X 11.0)
func testWhatever() {
// You test steps go here until you need the background foreground to run
XCUIDevice.shared.press(XCUIDevice.Button.home) // To background the app
XCUIApplication().activate() // To bring the app back
// You test continues after background foreground has been done.
}
If somebody needs just move app back from background i have written (based on answer above) category that really works(great thanks to pointing to FB git)
#implementation XCUIApplication(SpringBoard)
+ (instancetype)springBoard
{
XCUIApplication * springboard = [[XCUIApplication alloc] performSelector:#selector(initPrivateWithPath:bundleID:)
withObject:nil
withObject:#"com.apple.springboard"];
[springboard performSelector:#selector(resolve) ];
return springboard;
}
- (void)tapApplicationWithIdentifier:(NSString *)identifier
{
XCUIElement *appElement = [[self descendantsMatchingType:XCUIElementTypeAny]
elementMatchingPredicate:[NSPredicate predicateWithFormat:#"identifier = %#", identifier]
];
[appElement tap];
}
#end
For Swift, you need to declare the XCUIApplication private methods interface in Bridging-Header.h like this:
#interface XCUIApplication (Private)
- (id)initPrivateWithPath:(NSString *)path bundleID:(NSString *)bundleID;
- (void)resolve;
#end
Then call resolve() in your test cases to bring the app back:
XCUIApplication().resolve()
Since Xcode 13 we got several errors that the app was not in foreground state after returning to the app.
applying this code to our "goToSpringboardAndBack()" works
XCUIDevice.shared.press(XCUIDevice.Button.home)
if XCUIApplication().wait(for: .runningBackground, timeout: 5.0) {
XCUIApplication().activate()
}
_ = XCUIApplication().wait(for: .runningForeground, timeout: 5.0)
ยดยดยด

Aviary SDK crash on initializing on iOS

I integrate Aviary SDK on my app to enhance my app image editor feature. I read its documents, run its sample code and it works fine. But when run on my app, I face an issue. It crashed EXC_BAD_ACCESS after run over a method
[AFOpenGLManager beginOpenGLLoad];
I followed the setup guide on Aviary document
https://developers.aviary.com/docs/ios/setup-guide#project-setup
At first, I just create a Singleton manager to manage. I call [AFOpenGLManager beginOpenGLLoad]; on init function
- (id)init {
if (self = [super init]) {
[AFOpenGLManager beginOpenGLLoad];
}
return self;
}
- (void) launchPhotoEditorWithImage:(UIImage *)editingResImage
highResolutionImage:(UIImage *)highResImage
fromController:(UIViewController *)controller
{
// Customize the editor's apperance. The customization options really only need to be set
once in this case since they are never changing, so we used dispatch once here.
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self setPhotoEditorCustomizationOptions];
});
// Initialize the photo editor and set its delegate
AFPhotoEditorController * photoEditor = [[[AFPhotoEditorController alloc]
initWithImage:editingResImage] autorelease];
[photoEditor setDelegate:self];
// If a high res image is passed, create the high res context with the image and the
photo editor.
if (highResImage) {
[self setupHighResContextForPhotoEditor:photoEditor withImage:highResImage];
}
// Present the photo editor.
[controller presentViewController:photoEditor animated:YES completion:nil];
}
After run over the init function, it crashed on
Do I miss somethings, the sample code run well.
Edit 1:
compileShader is called from createProgram but I can read this method
Edit 2:
I realize somethings. My app project has a lib named libmediastreamer_voip.a . I think there is misunderstanding. I mean maybe Aviary lib and libmediastreamer_voip.a lib also have the function named compileShader. So when on Aviary lib calls compileShader it runs on compileShader on Aviary lib but run into compileShader on libmediastreamer_voip.a.
I wonder I could be like that? I create a new project and integrate Avairy SDK, it works well, just integrate to my app it crashes
I am a member of the iOS team at Aviary. This is caused by a conflict between our compileShader function and yours. Our function was not properly namespaced and resulted in the conflict. We will be addressing this in the next release of the SDK.
Michael
What I think about it. Check your shader value. It should have correct shader path from your resources or somewhere else with appropriate type (GL_VERTEX_SHADER or GL_FRAGMENT_SHADER).
Seems to me you've it's nil

how to respond to revmob sdk uialertview delegate?

Im trying to implement revmob sdk,
it works fine but their documentation dont have much detail and support not responding.
(http://sdk.revmob.com/sdks/ios/docs/index.html)
is there a way to use the delegate to know the status of the alertbox ?
this is what I currently use to call:
[BCFAds showPopupWithAppID:#"appId" withDelegate:nil];
after starting to ask the question I found the answer,
so incase someone else have this problem here is the solution.
to your .h file add a delegate called BCFAdsDelegate.
add #import "BCFAds.h"
in the .m file where you call the sdk add
[BCFAds showPopupWithAppID:#"appId" withDelegate:self];
use the method you want:
- (void)popupDidDismissActive;
// Called when user is back to the app
- (void)popupDidReceive;
// Called when a popup is available
- (void)popupDidFail;
// Called when a popup is not available
- (void)popupDidBecomeActive;
// Called when popup is displayed
- (void)popupDidDismissActive;
// Called when user is back to the app
- (void)userWillLeaveApplication;
// Called when user clicked and is about to leave the application

Resources