iOS - How does Cordova invoke objective c function? - ios

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.

Related

How to show native iOS views in a Flutter application?

I am currently working on a project in which I need to implement a graphical framework that has been written for Android and iOS; however, I am writing the application using Flutter/Dart, and so far I can not find any way for showing native iOS views in a Flutter application. I have found a module written for android that claims to do this (blog post), and I am curious if anyone knows of any modules or techniques that can achieve this for iOS.
I know that Flutter has the ChannelMethod feature, but that is not a solution-at least from my understanding, ChannelMethods can pass platform-specific messages, but this does not help me show a platform-specific plugin in a Flutter application.
It has also occurred to me to hard code an equivalent graphic interface in Flutter and then use ChannelMethods to pass the needed data, but this is not ideal because it appears that not all data I would need from the plugin is easily available. I'm really looking for a way to show the UIView in Flutter somehow.
Is there any way to show a native iOS view in a Flutter application?
Alternatively, is there any way to segue to a iOS viewController from a Flutter application?
You can use Flutter Platform Views to display platform native widgets in the Flutter app.
In the sample given in the docs, FLNativeViewFactory creates the platform view, and it provides a reference to the UIView. The iOS Views can be added using the provided UIView reference.
Using Swift
class FLNativeView: NSObject, FlutterPlatformView {
init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger?
){
_view = UIView()
super.init()
// iOS views can be added here
}
}
Using Objective-C
#implementation FLNativeView {
UIView *_view;
}
- (instancetype)initWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args
binaryMessenger:(NSObject<FlutterBinaryMessenger>*)messenger {
if (self = [super init]) {
_view = [[UIView alloc] init];
}
// iOS views can be added here
return self;
}
#end

Accessing a React Native module from other native code

I use a native module that works great for getting device info in React Native, in the JS code. I'd like to also make use of it's functionality in other native (Objective-C) code.
Is it possible to access functionality of React Native custom modules from other native code?
You can either access the functionality directly (using -[RNDeviceInfo deviceName] method) or using the way React Native is accessing it, that is:
RNDeviceInfo *rn = [[RNDeviceInfo alloc] init];
NSLog(#"Device Name: %#", [rn constantsToExport][#"model"]);
I found one solution, that is admittedly a bit of a kludge. It does work, but I would imagine this is far from ideal.
At the top of the class that utilizes this code:
#interface RNDeviceInfo ()
- (NSString*) deviceName;
#end
Then I can make use of it like so:
RNDeviceInfo *rn = [[RNDeviceInfo alloc] init];
NSLog(#"Device Name: %#", [rn deviceName]);

Passing custom parameters to Phonegap plugin

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]];

Determining if Facebook app is installed from Unity

We are using the Facebook SDK for Unity (v6.0) and I'd like to now whether there's a way that I can check if the Facebook app is installed on the device.
The reason is an existing bug in the Facebook SDK (see here: bug)
I want to identify this scenario (occurs only when the FB app is installed), and react accordingly.
"In order to use a native plugin you firstly need to write functions
in a C-based language to access whatever features you need and compile
them into a library. In Unity, you will also need to create a C#
script which calls functions in the native library."
from http://docs.unity3d.com/Manual/NativePlugins.html
So, basically you need to write your code in Objective-C and provide the communication between the Unity and the Native Code.
The code that you need to implement for checking Facebook APP is;
(void) checkFacebookApp
{
if ([[UIApplication sharedApplication] canOpenURL:[NSURLURLWithString:#"fb://"]])
{
return true;
}
}
However you need some communication between the Unity and Xcode project. So;
class SomeScript : MonoBehaviour {
#if UNITY_IPHONE || UNITY_XBOX360
// On iOS and Xbox 360 plugins are statically linked into
// the executable, so we have to use __Internal as the
// library name.
[DllImport ("__Internal")]
#else
// Other platforms load plugins dynamically, so pass the name
// of the plugin's dynamic library.
[DllImport ("PluginName")]
#endif
private static extern float checkFacebookApp ();
void Awake () {
// Calls the FooPluginFunction inside the plugin
// And prints 5 to the console
bool check = checkFacebookApp ();
}
}

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

Resources