Pass data to Flutter View Controller - android

I have added flutter to a native iOS code. I have UIButton and on pressing this button, I am presenting a FlutterViewController. I have been following this.
Here's my code for presenting the FlutterViewController:
#objc
#IBAction func openProfile() {
print("open profile")
lazy var flutterEngine = FlutterEngine(name: "patient_profile_engine")
flutterEngine.run(withEntrypoint: "", libraryURI: "");
let profileVC =
FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
present(profileVC, animated: true, completion: nil)
}
This code is working fine and the flutter view is opening and since I haven't specified and entry point yet so it using the main.dart.
The problem is that I need to pass some information to the Flutter dart code. e.g. a dictionary ["patient_id": "123456"] during the initialization.
I will have to do the same in Android native Java code as well.
Is there any easy way?

You will probably want to write a platform channel to communicate between the native code and the flutter engine.
An alternative, for this purpose, would be to use runWithEntrypoint:initialRoute: method to start the engine, encode the data into the initial route, and parse it on the flutter side.

Related

Protractor locators does not work in PageObjectModel structure

Framework: Appium + Protractor + Cucumber + Typescript using POM model
I have the protractor framework for appium designed in POM structure
The initial page of the app will identify the locators calling in a different ts file and the functions such as tap, isDisplayed calling it in a different ts file.
But once it passes the initial pages in the app,say 3 pages. the locators are not identified which are calling other function, but they are identified when they are passed directly ( like driver.findelements(by.css('')).click ) this works.
The problem is I can't pass this code like this within the step definition .ts file always as it is not a good structure
Note: By the way, this script was working fine earlier.
tried to test using a different workaround, like building the binary again, trying to run on android and ios application, downgrading or upgrading the node packages. But nothing solved the problem. has anyone faced this kind of issue. Any suggestions or solutions for this problem, please?
Code which works: (Passing the locators directly in the function, rather than from the onboarding.ts file will work)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await browser.driver.findElement(by.css('button[sp-automation-id=\'select-state-toggle\']')).click();
await browser.driver.findElement(by.css('page-action-sheet label[sp-automation-id=\'action-sheet-option-VIC\']')).click(); });
Code which does not work: (Onboarding.ts file contains the locators defined for State and VIC same as the above code block. But reading from there it does not work.)
Then(/^VIC should be selected from the state or territory drop down$/, async () => {
await AutomationAction.tap(Onboarding.State);
await AutomationAction.tap(Onboarding.VIC); });
Code which works (The below code is called before the above code block, it's a page before calling the above pages)
Then(/^I enter the mobile number and tap next button on the your mobile number screen$/, async () => {
MobileNo = AutomationAction.getMobileNumber("mobileNumber");
SameMobileNo = MobileNo;
await AutomationAction.sendKeyText(Onboarding.InputMobileNo,MobileNo);
await AutomationAction.tap(Onboarding.Next_BTN_YourMobileNumber);
});
Because of the page where it is failing the automation thinks its as non-angular page and the locators used to fail or not locate them when calling it in a different function. When I introduced browser.ignoreSycnhronization=true to make Angular sync for non-angular apps/pages it worked.

How to trigger in-app navigation based on API response

This question relates to both ios (swift) and android.
I'm working on building the backend implementation for a banner system that our mobile apps need to integrate with. Some of the banners need to redirect a user to a section of the app when pressed.
What is the best practice for triggering route navigation based on data returned in an API call?
For example, a list of banner objects in JSON where a key references the page to navigate to - would deep linking apply here, does it make sense for the apps to create a mapping of routes that I can reference by passing a string?
I feel like there has to be a simple solution here but the mobile team I'm working with seems pretty adamant.
In my current project (iOS), we are using deep links to map navigation to a certain tab of our app. So you could send it through JSON and then post a Notification, which your main controller is listening to (TabBarController for example), and then select the wanted index to go to, or any other navigation logic you need.
// Registering the deeplink with DeepLinkKit pod (https://github.com/button/DeepLinkKit)
self.router?.register("a/created/path") { link in
if let link = link {
debugPrint("Router: \(String(describing: link.url))")
NotificationCenter.default.post(
name: Notification.Name(Configuration.App.kGoToSomewhere),
object: nil
)
}
}
Or just extracted from your JSON and then setup the notification
call { URL in
NotificationCenter.default.post(
name: Notification.Name("ANotification"),
object: nil
)
}
And then in your main controller
class MainTabBarController: UITabBarController {
func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(selectTab),
name: Notification.Name("ANotificaton"),
object: nil
)
}
}
func selectTab() {
// Do your navigation logic here
}
I hope it helps!

How can we call angular functions by native javascript in angular 4

In Angular 1.x , we can use angular.element(appElement).scope() to get $scope, and then use the $apply(), so that the native javascript can directly call angular functions or two-way binding. While with Angular 4, how could we call angular functions or two-way binding by native javascript or the android native.
For example :
The web is developed by angular 4, and it will be used in the android webview, so it needs an interaction with android, how can i handle the interaction?
I can think of many ways, but have never read anything in the manuals which clarifies as to the most Angular way.
Zones
You have to keep in mind that Angular uses zones and a change detection tree at the core of it's engine. So any outside access needs to happen in that context.
You have to run external code in the Angular zone:
zone.run(() => {
// do work here
});
If you make changes to any data that will directly or indirectly effect a template expression you run the risk of a change detection error. So a component needs to inject ChangeDetectorRef and call markForCheck.
So if you code runs inside a component but from outside of Angular. You need to do this:
zone.run(() => {
// do work here.
this.ChangeDetectorRef.markForCheck();
});
Still, that raises the question. How do I get to the component?
Accessing Angular
You have to bootstrap your Angular application so that it can be accessed.
When you bootstrap your Angular application the browser service returns a promise to the main module. That main module contains the injector and from there you can access any exported services.
platformBrowserDynamic()
.bootstrapModule(AppModule)
.then((modRef: NgModuleRef<AppModule>) => {
window.myGlobalService = modRef.injector.get(MyServiceClass);
});
That would place a service class as a global variable. You would have to create an API that forwards to Angular's zones.
#Injectable()
export class MyServiceClass {
public dataEmitter: Subject<any> = new Subject();
public constructor(private zone: NgZone) {}
public fooBar(data: any): any {
return this.zone.run(()=>{
// do work here
this.dataEmitter.next(data);
return "My response";
});
}
}
You can return a result from zone.run out of the service. The key is that Angular code is run in the correct zone.
Easy Component One-Way Binding
The easiest solution for one-way data binding is to just use the Event module for the DOM.
#Component({....})
export class MyComponent {
#HostListener('example',['$event'])
public onExample(event: Event) {
console.log(event.fooBar);
}
}
// else where in external JavaScript
var elem; // the DOM element with the component
var event = new Event('example', {fooBar: 'Hello from JS!'});
elem.dispatchEvent(elem);
I prefer this approach since Angular handles the event listener as it would any other kind of event (i.e. click events)
You can also do this the other way around. Have the component emit DOM events on it's ElementRef for external JavaScript to listen for. This makes the whole two-way communications more DOM standard.

How to properly use iOS only components in React Native without error in Android

I'm new to React Native and testing out PushNotificationIOS. But the checkpermission call is giving me error on Android.
ExceptionsManager.js:61 Cannot read property 'checkPermissions' of undefined
I'm guessing this is because I need to only use the component on iOS. How do I add a check of the OS to make the call only on iOS?
Here's my code:
componentWillMount: function() {
//-- need an OS check here??
PushNotificationIOS.checkPermissions((data)=> {
console.log("in comp will mount: checking for permission")
console.log(data.alert)
console.log(data.badge)
What I would suggest is splitting that platform specific code in separate files.
React Native will detect when a file has a .ios. or .android.
extension and load the relevant platform file when required from other
components.
MyFile.ios.js
MyFile.android.js
You can then require the component as follows:
const MyFile= require('./MyFile');
and use it like this
componentWillMount: function() {
//-- it would call the logic of what ever platform was detected automatically
MyFile.CallWhatEver();
And it will run the platform specific code.
Another way is the
Platform Module
React Native provides a module that detects the platform in which the
app is running. You can use the detection logic to implement
platform-specific code. Use this option when only small parts of a
component are platform-specific.
if(Platform.OS === 'ios')
There is also a platform.select that can accept any value
const Component = Platform.select({
ios: () => //function goes here,
android: () => require('ComponentAndroid'),
})();
link
https://facebook.github.io/react-native/docs/platform-specific-code.html

How to create async call with jquery with android using phonegap?

I have seen background service in phonegap and integrated successfully but, I need to make an ajax call to get the data from server.This call need to be happen in background process without disturbing the UI. I am unable to do this using this plugin.
And my code look like,
$.ajax({
type: "POST",
url: "http://example.com/xxx",
dataType: "xml",
async:true,
success: function (data) {
var serializer = new XMLSerializer();
var xmlString = serializer.serializeToString(data);
var finalxml= xmlString.replace(/</g, '<').replace(/>/g, '>').replace('<br/>','\n');
window.localStorage.setItem("xml_Questions",finalxml);
}
});
This ajax call has to be done with async(background) call while user doing something..
But user is not able to do anything until get the response.So I have followed Background service plugin for phonegap, but I am not able to implement this method with that plugin.
Can we do this?
Can anybody help me?
Thank you in adv...
Your $.ajax code looks right to me, so it shouldn't block the app behavior.
I don't completely understand your question... user shoudn't be allowed to do anything until the localstorage.setitem is set? If this is right, you could use jquery to enable some kind of "NEXT" button after the setItem instruction, so the user won't be able to move on until the async call is done.

Categories

Resources