I am implementing admob in my iOS module using this guide.
I have a view controller where my interstitial ads are initialized like this
#CustomClass
public class ViewController extends UIViewController implements ActionResolver {
private GADInterstitial interstitial;
private static final String AD_UNIT_ID = "ca-app-pub-XXXXXXXXXXXXXXXX-XXXXXXXXXX";
public ViewController() {
viewDidLoad();
}
#Override
public void viewDidLoad() {
super.viewDidLoad();
interstitial = createAndLoadInterstitial();
}
private GADInterstitial createAndLoadInterstitial() {
//Ad Unit ID of your interstital, from adMob account.
GADInterstitial interstitial = new GADInterstitial(AD_UNIT_ID);
System.out.println("Add unit ID is " + AD_UNIT_ID);
interstitial.setDelegate(new GADInterstitialDelegateAdapter() {
#Override
public void didDismissScreen(GADInterstitial ad) {
ViewController.this.interstitial = createAndLoadInterstitial();
}
});
interstitial.loadRequest(createRequest());
return interstitial;
}
private GADRequest createRequest() {
GADRequest request = new GADRequest();
// To test on your devices, add their UDIDs here:
request.setTestDevices(Arrays.asList(GADRequest.getSimulatorID()));
return request;
}
#IBAction
public void showInterstitialAd() {
if (interstitial.isReady()) {
interstitial.present(UIApplication.getSharedApplication().getKeyWindow().getRootViewController());
System.out.println("Interstitial is loaded.");
} else {
interstitial.loadRequest(createRequest());
System.out.println("Interstitial not ready!");
}
}
}
My implementation is similar to this guide also.
When I run my app on the simulator I get the following exception.
org.robovm.objc.ObjCClassNotFoundException: GADInterstitial
at org.robovm.objc.ObjCClass.getByType(ObjCClass.java:251)
at org.robovm.objc.ObjCClass.getFromObject(ObjCClass.java:212)
at org.robovm.objc.ObjCObject.getObjCClass(ObjCObject.java:161)
at org.robovm.apple.foundation.NSObject.alloc(NSObject.java:214)
at org.robovm.objc.ObjCObject.<init>(ObjCObject.java:79)
at org.robovm.apple.foundation.NSObject.<init>(NSObject.java:157)
at org.robovm.pods.google.mobileads.GADInterstitial.<init>(GADInterstitial.java:52)
at com.nauv.fut.simulator.ViewController.createAndLoadInterstitial(ViewController.java:39)
at com.nauv.fut.simulator.ViewController.viewDidLoad(ViewController.java:34)
at com.nauv.fut.simulator.ViewController.<init>(ViewController.java:27)
at com.nauv.fut.simulator.IOSLauncher.createApplication(IOSLauncher.java:30)
at com.badlogic.gdx.backends.iosrobovm.IOSApplication$Delegate.didFinishLaunching(IOSApplication.java:65)
at com.badlogic.gdx.backends.iosrobovm.IOSApplication$Delegate.$cb$application$didFinishLaunchingWithOptions$(IOSApplication.java)
at org.robovm.apple.uikit.UIApplication.main(Native Method)
at org.robovm.apple.uikit.UIApplication.main(UIApplication.java:413)
at com.nauv.fut.simulator.IOSLauncher.main(IOSLauncher.java:35)
I have imported the admob framework on my ios build.gradle. I have also tried moving it to ios module in main build.gradle though this doesnt change anything. How can I fix this error? My class is being imported correctly and I am using project.ext.robopodsVersion = "1.14.0" on my app build.gradle.
Fortunately some people forked the project and I have found a working solution :)
The fork : https://github.com/MobiDevelop/robovm-robopods
I did the following.
Gradle:
Build script dependency
dependencies {
...
classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.2.0-SNAPSHOT'
}
IOS Project dependencies:
...
compile "com.mobidevelop.robovm:robopods-google-mobile-ads-parent:2.2.0-SNAPSHOT"
compile "com.mobidevelop.robovm:robopods-google-mobile-ads-ios:2.2.0-SNAPSHOT"
compile "com.mobidevelop.robovm:robovm-rt:2.2.0-SNAPSHOT"
compile "com.mobidevelop.robovm:robovm-cocoatouch:2.2.0-SNAPSHOT"
Download SDK from here
Copy the GoogleMobileAds.framework folder in ios/libs
Modify the robovm.xml file (I went completely overkill on the frameworks list but I was tired of compilation error, if you find the ones that are not necessary, feel free to let me know):
<config>
...
<frameworkPaths>
<path>libs</path>
</frameworkPaths>
<frameworks>
<framework>UIKit</framework>
<framework>OpenGLES</framework>
<framework>QuartzCore</framework>
<framework>CoreGraphics</framework>
<framework>OpenAL</framework>
<framework>AudioToolbox</framework>
<framework>AVFoundation</framework>
<framework>AdSupport</framework>
<framework>AudioToolbox</framework>
<framework>CoreMedia</framework>
<framework>CoreMotion</framework>
<framework>CoreVideo</framework>
<framework>CoreTelephony</framework>
<framework>CoreBluetooth</framework>
<framework>SafariServices</framework>
<framework>EventKit</framework>
<framework>EventKitUI</framework>
<framework>MediaPlayer</framework>
<framework>MessageUI</framework>
<framework>StoreKit</framework>
<framework>SystemConfiguration</framework>
<framework>GoogleMobileAds</framework>
<framework>VideoToolbox</framework>
<framework>GLKit</framework>
</frameworks>
</config>
And this works (for me)
Related
I would like to access iOS Healthkit, eventually Android too but cannot find out a successful way to do it. Online I've seen advice pointing to https://learn.microsoft.com/en-us/xamarin/ios/platform/healthkit which is for xamarin and not MAUI, but the methods in the example are not found. This is the code:
private HKHealthStore healthKitStore = new HKHealthStore ();
public override void OnActivated (UIApplication application)
{
ValidateAuthorization ();
}
private void ValidateAuthorization ()
{
var heartRateId = HKQuantityTypeIdentifierKey.HeartRate;
var heartRateType = HKObjectType.GetQuantityType (heartRateId);
var typesToWrite = new NSSet (new [] { heartRateType });
var typesToRead = new NSSet ();
healthKitStore.RequestAuthorizationToShare (
typesToWrite,
typesToRead,
ReactToHealthCarePermissions);
}
void ReactToHealthCarePermissions (bool success, NSError error)
{
var access = healthKitStore.GetAuthorizationStatus (HKObjectType.GetQuantityType (HKQuantityTypeIdentifierKey.HeartRate));
if (access.HasFlag (HKAuthorizationStatus.SharingAuthorized)) {
HeartRateModel.Instance.Enabled = true;
} else {
HeartRateModel.Instance.Enabled = false;
}
}
Unfortunately,
HKQuantityTypeIdentifierKey.HeartRate;
HKObjectType.GetQuantityType (heartRateId);
Seem to be missing. Has anyone got a working example for MAUI?
These two methods in the documentation you refer to are outdated, you can modify your method as follows:
HKQuantityTypeIdentifierKey.HeartRate; ---> HKQuantityTypeIdentifier.HeartRate;
HKObjectType.GetQuantityType (heartRateId); ---> HKQuantityType.Create(heartRateId);
For more details, you can refer to:
HealthKit Namespace | Microsoft
HKQuantityTypeIdentifierKey Class | Microsoft
HKObjectType.GetQuantityType(NSString) Method | Microsoft
I used this code in my .Net Maui app since you asked for both iOS and Android. You can see an auth request for heart rate, but the code doesn't actually query for or observe heart data. Anyway, this code is a great guide to start with. The code also implements completion handlers across iOS and Android.
https://github.com/jlmatus/Xamarin-Forms-HealthKit-steps/blob/master/StepsCounter-Test-Project/iOS/HealthData.cs
Hope this helps!
I am creating a NativeScript plugin that will work with my iOS and Android SDKs. In my iOS code, I have an optional #protocol that contains a few optional methods with callbacks about the state of the SDK. I am now trying to access this protocol in NativeScript, and I tried searching the internet and following the guide here, but unfortunately, I still have issues with it. Here is a part of the #protocol in iOS:
#protocol BLASessionDelegate <NSObject>
#optional
- (void)sessionInitialized;
...
Here is the code I put in the "index.d.ts" in my plugin:
export interface SessionDelegate {
sessionInitialized?();
...
}
Here is the part in the "bla.ios.d.ts" file in my plugin:
declare interface BLASessionDelegate extends NSObjectProtocol {
sessionInitialized?();
}
#NativeClass()
declare class BLASessionDelegateImpl extends NSObject implements SessionDelegate {
static ObjCProtocols = [BLASessionDelegate];
static new(): BLASessionDelegateImpl {
return <BLASessionDelegateImpl>super.new(); // calls new() on the NSObject
}
sessionDelegate: SessionDelegate;
public sessionInitialized() {
console.log("Adi - inside sessionInitialized");
if(this.sessionDelegate.sessionInitialized !== undefined) {
this.sessionDelegate.sessionInitialized();
}
}
}
Here is the part in the "bla.ios.ts" file in my plugin:
export const setSessionDelegate = function(sessionDelegate: SessionDelegate) {
if(typeof(bla) !== "undefined") {
console.log("Adi - in the setSessionDelegate");
let delegate: BLASessionDelegateImpl = BLASessionDelegateImpl.new();
delegate.sessionDelegate = sessionDelegate;
bla.setSessionDelegate(delegate);
}
}
This is the code I put in the test app in the "app.ts" file:
let delegate: bla.SessionDelegate = {
sessionInitialized: function() {
const sessionLink: string = bla.generateSessionLink();
console.log("Adi - sessionLink = ", sessionLink);
}
}
bla.setSessionDelegate(delegate);
I am still getting the following error with a crash when running the app and I can't figure out why:
***** Fatal JavaScript exception - application has been terminated. *****
NativeScript encountered a fatal error: Uncaught ReferenceError: BLASessionDelegateImpl is not defined
at
setSessionDelegate(file: app/webpack:/myCoolApp/work/native-script-plugin/native-script/src/bla.ios.ts:165:41)
at ./app/app.ts(file: app/webpack:/myCoolApp/app/app.ts:18:0)
at __webpack_require__(file: app/webpack:/myCoolApp/webpack/bootstrap:24:0)
at __webpack_exec__(file:///app/bundle.js:839:39)
at (file:///app/bundle.js:840:318)
at __webpack_require__.X(file: app/webpack:/myCoolApp/webpack/runtime/startup entrypoint:6:0)
at (file:///app/bundle.js:840:47)
at (file:///app/bundle.js:845:3)
at require(:1:137)
I am writing an NPM library that contains iOS & Android native modules. Important is that I need to pass parameters to the native module before startup. This works great for Android:
package ...
import com.facebook.react.bridge.*
class MyNativeModule(reactContext: ReactApplicationContext, parameter: String) {
override fun getName(): String {
return "MyModule"
}
#ReactMethod
fun retrieveParameter(promise: Promise) {
promise.resolve(parameter)
}
}
When turning off autolinking a library user can just create their own RN package and use the following to set the parameter:
class MyAppRNPackage(private val voizeCore: VoizeCore = VoizeCore.getInstance()) : ReactPackage {
override fun createNativeModules(reactApplicationContext: ReactApplicationContext): List<NativeModule> {
return arrayListOf<NativeModule>(
MyNativeModule(reactApplicationContext, "this is the parameter"),
)
}
override fun createViewManagers(reactApplicationContext: ReactApplicationContext): List<ViewManager<*, *>> {
return emptyList()
}
}
In iOS the native module would look something like this:
// MyNativeModule.m
#import "MyNativeModule.h"
#implementation MyNativeModule
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(retrieveParameter:(RCTPromiseResolveBlock)resolve rejecter: (RCTPromiseRejectBlock)reject)
{
resolve(???)
}
#end
But how is it possible to set a parameter for the iOS module? The problem is that in iOS, native modules can not be registered manually. Furthermore, only classes are registered not class instances.
Any idea how you could pass parameters from native code to the iOS native module?
The question can be really basic since I have little to no knowledge about Xamarin Forms.
I have recently started working on an old Xamarin Forms project where I had to upgrade "Prism.Plugin.Popups" plugin to Version="7.2.0.1046"
and “Prism.Unity.Forms" to Version="7.2.0.1422"
I had to Implement IInitialize Interface since INavigatingAware is deprecated in latest Prism framework as mentioned in https://github.com/PrismLibrary/Prism/issues/1858
Issue:
I want app to navigate back from XPopupPage to AViewModel with the code _navigationService.GoBackAsync(navParams); which is working but Initialize function of AViewModel isn’t getting called once it comes back from XPopupPage.
Here’s the code:
AViewModel:
public class AViewModel : BindableBase, INavigationAware, IInitialize {
....
// Code to navigate to XPopupPageViewModel private void ShowPopup(object obj)
{
_navigation.NavigateAsync($”{.....}”);
}
//NOT GETTING CALLED once it come back from XPopupPageViewModel
public void Initialize(INavigationParameters parameters) {
.....
} }
XPopupPageViewModel:
public class XPopupPageViewModel : BindableBase, INavigationAware, IInitialize
{
//Code to navigate back to AViewModel private void Update(object obj)
{
....
var navParams = new NavigationParameters(.....); _navigationService.GoBackAsync(navParams);
} }
From the github issue you posted:
Use OnNavigatedTo when calling GoBack
I'm trying to extend AKNode and AKToggelable and this error appears on Project-Swift.h file
What is the way to do this?
My class is
class AKCustom: AKNode, AKToggleable, AKComponent, AKInput {
public typealias AKAudioUnitType = AKBalancerDeplikeAudioUnit
public static let ComponentDescription = AudioComponentDescription(mixer: "dpba")
private var internalAU: AKAudioUnitType?
open dynamic var isStarted: Bool {
return internalAU?.isPlaying() ?? false
}
public init( _ input: AKNode? = nil) {
_Self.register()
super.init()
AVAudioUnit._instantiate(with: _Self.ComponentDescription) { [weak self] avAudioUnit in
self?.avAudioNode = avAudioUnit
self?.internalAU = avAudioUnit.auAudioUnit as? AKAudioUnitType
input?.connect(to: self!)
}
}
open func start() {
internalAU?.start()
}
open func stop() {
internalAU?.stop()
}
}
And error messages in Project-Swift.h file:
Cannot find interface declaration for 'AKNode', superclass of 'AKCustom'
No type or protocol named 'AKToggleable'
add #import "AudioKit/AudioKit-Swift.h" to PROJECT-Bridging-Header.h. Then AKNode will be accessible at Project-Swift.h.
Inside the AudioKit folder is a "Developer" folder that has examples for "Extending AudioKit" on both iOS and Mac. That's probably the best place to start. Make sure you're including the source as a framework properly - the examples in this folder show you how to do it either with source directly or the precompiled framework.