I'm integrating some third-party SDKs into my iOS application. In our app, we have some in-app-purchases available. We are adding our purchase manager as a transaction observer, but I'm wondering if we can find out if these other third-party SDKs are listening to our IAPs and collecting that information. I've searched through the StoreKit API, but I can't find a way to list all the transaction observers. Anybody have any ideas?
There isn't a public API available for this, but you can always swizzle the -[SKPaymentQueue addTransactionObserver:] method in your development build and add a debugger breakpoint (or just perform some logging) in your swizzled implementation of this method in order to find out.
Starting iOS 14, SKPaymentQueue class allows retrieving a list of all transaction observers.
Related
We are using the latest available version of the Facebook SDK for Unity (v7.2.2)
One of the available APIs is ActivateApp (FB.ActivateApp).
Should this method be called, specifically on iOS ?
Digging a bit into what's under the hood (the SDK is open source), I see that on iOS (in the file FBUnityInterface.mm), there's the following code:
- (void)didBecomeActive:(NSNotification *)notification
{
[FBSDKAppEvents activateApp];
}
It looks like ActivateApp is being called automatically (whether i manually call it or not).
Should we call FB.ActivateApp when our app starts / resumes? won't this cause duplicate app activation reports ?
Answering my own question:
On iOS, ActivateApp seems to be called automatically in iOS native code.
Invoking the FB.ActivateApp method does nothing (see this code from IOSFacebook.cs):
public override void ActivateApp(string appId)
{
IOSFacebook.IOSFBSettingsActivateApp(appId);
}
The called method is simply empty:
private static void IOSFBSettingsActivateApp(string appId)
{
}
So, this seems to be taken care of automatically on iOS.
Just to chime in here. We currently had a bug where when using UnityIAP, if a user bought a consumable IAP and quit the app before marking it Complete, they wouldn't get notified of the purchase on app restart.
In the end it came down to Facebook's automatic logging of IAP events in iOS (SDK >= 3.22). I think because it was adding a listener to the transaction queue before Unity.
I mention this because to turn on FB's auto logging of IAP, you need to set it in:
developers.facebook.com > App > Settings > Basic > iOS > iOS Only: Log In-App Purchase Events Automatically (Recommended)
Then call ActivateApp(). However, this is done automatically for you on iOS, so that only leaves the setting on the website or changing the code.
Long story short, if you're using Unity IAP and you're not getting purchase callbacks for incomplete purchases on iOS startup, it's either because of FB or another plugin adding a transaction queue listener (another user reported the possibility of AdMob). For us it was FB.
http://forum.unity3d.com/threads/iap-restorepurchase-on-ios-not-return-processpurchase-callback.392000/
I am working on a mobile app using Ionic (with Cordova purchase plugin) but this question is more general. We are using In App Purchases (IAP) and are currently getting an error when we try to finish the consumable purchase. Our current flow is like this:
Get list of our Products from Apple and render on our IAP page
User clicks consumable IAP they want and it fire off a message to StoreKit initiating the purchase
We get a response with a consumable IAP object with the state set to approved.
We initiate the verification procedure with a callback to our own server where we hit apple up to verify the purchase and then log it on our database and send the app a 200 response (not sure if we need to send back the IAP object here with receipt from our server or we just work with the one already inside the app?)
We try finish the purchase where we get an error saying (InAppPurchase[objc]: Cannot finish transaction)
My question is assuming this is the correct flow what does the finish method do? Looking in the source code of the Cordova Purchase Plugin wrapper I can see it sets the state of the object to finished but I am assuming (I couldn't find the code where this happens) it also talks to Apple so that Apple marks the purchase as finished on their side? If we manually set the state to finished the IAP error goes away but the consumable can still not be purchased multiple times which means to me that Apple also need to close it. Is this a correct assumption? Any other tips to getting this to work would also be appreciated.
I'm not sure how cordova handles IAP, but on the apple side, the transaction needs to be finished by calling finishTransaction. It would appear thats the step thats not working.
One thing that might happen due to the delay in going to the server to validate is that the original transaction object has expired, and calling finishTransaction with it does nothing. At this point you might be able to search for your transaction in: [[SKPaymentQueue defaultQueue] transactions]
If you can grab it from there then call finishTransaction then it should work. Not sure how you do this with cordova but I hope this helps.
I just get started with WatchKit and I'm trying to do this (if I'm not wrong, it is possible to do): I'd like the WatchKit Extension to ask the containing app for requesting some data to a web service, and then return the service response to the Extension to update the WatchKit App interface accordingly.
As I read in Apple Watch Programming Guide, yo can call the openParentApplication:reply: method in the WatchKit Extension to request something to its containing app, and then the application:handleWatchKitExtensionRequest:reply: method in the AppDelegate of the containing app should be called. Once this method called, I need to perform the service request, wait for its response, and then send it back to the Extension.
However, when I run the WatchKit App scheme in the simulator, the openParentApplication:reply: method is called, but a breakpoint within the application:handleWatchKitExtensionRequest:reply: is not reached. So I'm not even able to test if I can correctly perform the web service request and get its response back.
What could I be missing? Should I configure somehow the schema to reach breakpoints in the containing app as well? Is it needed to declare some kind of background feature for this?
Thanks in advance
I just answered a very similar question here which will allow you to open the iOS app from the Watch Extension and getting a reply back.
In order to debug the iOS app while running the Watch Extension, you should follow the steps explained here.
I'm using ProductStore by Adobe to implement In-App Purchase on iOS.
I can purchase a product, it works fine. (I listen to PURCHASE_TRANSACTION_CANCEL, PURCHASE_TRANSACTION_FAIL and PURCHASE_TRANSACTION_SUCCESS, _productStore.makePurchaseTransaction(PRODUCT_ID), call _productStore.makePurchaseTransaction(PRODUCT_ID), and than event PURCHASE_TRANSACTION_SUCCESS is fired)
Also I have to know if the product was purchased already. So I listen to RESTORE_TRANSACTION_COMPLETE, RESTORE_TRANSACTION_FAIL and RESTORE_TRANSACTION_SUCCESS events and call restoreTransactions(). When all the previous transactions are done firing their PURCHASE_SUCCEEDED events, RESTORE_TRANSACTION_COMPLETE should be dispatched. But I receive the RESTORE_TRANSACTION_COMPLETE and no RESTORE_TRANSACTION_SUCCESS.
So, questions:
When I'm testing my app, Sandbox is proceeding all my requests. May the problem be related to Sandbox?
In _productStore.pendingTransactions I do have one transaction with receipt and with my PRODUCT_ID. What does it mean?
Thank you in advance,
Olga
Caveat: I know that private frameworks won't fly in the App Store.
I'm trying to use the BluetoothManager framework to let me 1) check if Bluetooth is enabled on a device, and 2) if not on, turn it on.
I can successfully load BluetoothManager per the instructions found here, but once I've done so, BluetoothManager just doesn't seem to do anything.
Calling enabled always returns NO, even when Bluetooth is enabled. Calling setEnabled never changes its state. Absolutely every other BluetoothManager call I've tried always returns NO, nil, zero-element arrays, etc. In short, the BluetoothManager that gets returned seems totally neutered. (I'm running off my 4.2.1 iPhone, not the simulator.)
I've seen posts from people who claim to have gotten this working, yet I haven't been able to get a response from them. Can anyone shed light on why this might not be working?
Thanks very much.
It takes a second for the BluetoothManager to startup and attach to the BTServer. I just did a quick call to the shared instance - [BluetoothManager sharedInstance]; - to force it to init. Once it's finished init it will post a BluetoothAvailabilityChangedNotification. I'd just listen for that and try [[BluetoothManager sharedInstance] setEnabled:YES]; in the notification callback.
FYI, the object included in the NSNotification for BluetoothAvailabilityChangedNotification is a boolean, so you should be able to check that to make sure that Bluetooth is really available.
That's because of IPC. BluetoothManager communicates via sendMsg et el. Use for example NSTimer to query BluetoothManager sharedInstance so your program has time to receive and process messages.
There is a demo project on Github called BeeTee for demonstrating the private framework BluetoothManager.