Discussion Forums  >  Plugins, Customizing, Source Code

Replies: 11    Views: 152

Absentia
buzztouch Evangelist
Profile
Posts: 960
Reg: Oct 20, 2011
Alaska
20,600
11/15/12 10:45 PM (13 years ago)

calling all code gurus

Hey guys, this entire post is concerning the theMonster's awesome In App Purchase plugin so if you don't have it I guess you might as well stop reading now. Despite being awesome, this plugin has a couple of rather frustrating issues - I've been occupying all of the last two days trying to fix it myself - I keep thinking I've figured it out, but obviously I haven't yet. It's frustrating because I have an app I'm pretty excited about submitting and I basically can't until the plugin is updated or I tweak it myself. So here's the problems I'm having - ISSUE 1 - Disappearing back button - This occurs randomly...once the user makes the purchase they will be taken to the unlocked screen and it will be missing the back button. I can't for the life of me figure out why this is happening ISSUE 2 - Only one IAP - As far as I can tell, this plugin currently only allows for 1 IAP. I have three different IAP's set up in my app and, unfortunately, purchasing one unlocks all three. I have tried messing around with the purchasePageFlag BOOL, but I am beginning to think its a bit more complex than that. I need to figure out a way to make it distinguish between numerous IAPs. Any ideas? So that's where I'm at right now - I understand if nobody feels like diving into the code and figuring it out, just had to send out one more call for help until this thing gets updated
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/16/12 02:47 AM (13 years ago)
I had a look at this a bit ago. 2nd thing first. It looks like the JSON data for the screen holds a productID and a uniqueID for the item you are selling. On line 80 (Easy_in_app_purchase.m) it creates a new string called savedPurchasedId. The string would look like: purchased_[the product id] If your productID was 1234 it would be purchased_1234 Next, it looks to see if there is a saved value on the device with this unique string. If it exists on the device, the product was already purchased. The completeTransaction() method on line 243 is what saves this value to the device. This means if this method never completes it will look as if the device never purchased this product. This also means that there should be no limit to the number of products you can "sell" so long as they each have a unique productID in the control panel. I guess I would start by making sure the productID value (from the JSON) is unique for each of the screens your're setting up. Use the BT_debugger and output it to the console...see what the value is? As far as the back button, yup...this is strange. Is the "unlocked screen" just like any other screen or is it something custom? When the screen appears it will fire the: [BT_viewUtilities configureBackgroundAndNavBar:self:[self screenData]]; for the screen you landed on. That's the method that shows / hides the back button. It's been a reliable method for a very long time. It's probably not related to the screen your landing on. It looks like line 91 of the IAP plugin is firing if you've already purchased the product. In other words, if you've already purchased the project, the IAP plugin should not even appear, you should go directly "through it" to the screen you purchased. This is what the goToPurchasedScreen method does. Is it related to the order in which the purchased screen is visited? Like maybe it works after they have purchased the product, closed the app, then re-opened it? Its' hard to say what's happening here. We'll see if TheMonster chimes in and we'll go from there.
 
Absentia
buzztouch Evangelist
Profile
Posts: 960
Reg: Oct 20, 2011
Alaska
20,600
like
11/16/12 11:44 AM (13 years ago)
Thanks a lot for the response, that actually did clarify a couple of things - my product Ids are are definitely all unique. Let me see if I'm interpreting this code right - The completeTransaction() method on line 243 calls the provideContent() method on line 208. The provideContent method() then calls the goToPurchasedScreen method on line 293 in which the purchasePageFlag BOOL is set to YES so here's where I'm a little confused - when the IAP screen is reloaded, wouldn't the following if statement always come out being true? - if([savedPurchasedId length] > 1 && !purchasePageFlag) How is it distinguishing between purchase Ids? It looked to me like once the first IAP was made, then the savedPurchaseId length will always be greater than 1 and the purchasePageFlag will always be YES. Of course there's a 75% chance that I am misreading this and have no idea what I'm talking about. As for the back button, there a couple more things I can specify - 1. The menu I'm loading is the Design Menu plugin 2. I have seen this debug error appear in conjunction with the bug a couple of times - "Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted"
 
Absentia
buzztouch Evangelist
Profile
Posts: 960
Reg: Oct 20, 2011
Alaska
20,600
like
11/16/12 12:48 PM (13 years ago)
I also just now encountered an error where if I purchase a locked quiz, when the IAP screen jumps to the quiz screen it is just a blank white screen - here's the error for that - "Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted. 2012-11-16 10:46:20.094 onedirectiontriviagame[1587:907] Unbalanced calls to begin/end appearance transitions for <BT_screen_quiz: 0x1f880660>."
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/16/12 01:41 PM (13 years ago)
This is 100% for sure the trouble with the implementation. The implementation meaning how the IAP plugin is "removing itself" when the product is already purchased. This is for sure the method that's triggering that iOS warning: [allViewControllers removeObjectIdenticalTo:self] That method should be changed to something else because firing it in the viewDidAppear appears to be confusing it. Not sure of the solution yet...will find one. productID: Yes, you're right, savedPurchasedId will always have a greater than 1 but ONLY after a particular productID has been purchased. The length of it comes from: NSString *savedPurchasedId = [BT_strings getPrefString:[NSString stringWithFormat:@"purchased_%@", productID]]; "go to the saved preferences on this device and find a saved preference for a key with this value" If this product has never been purchased, savedPurchasedId should equal @"" (empty string). This value is only set (Saved to preferences) in one place...line 250. When it saves the value it is saving it with the productID for this screen. This means it should only exist if this product was purchased, and not another product on a different screen with a different product id. It's a matter of seeing what value is being saved to preferences when the transaction completes. It should save a different value for each productID (each screen). Maybe I'm missing some logic...Try this: Change line 91 from: else if ([savedPurchasedId length] > 1 && purchasePageFlag) // already purchased but going from the back button To this: else if ([savedPurchasedId isEqualToString:productID] && purchasePageFlag) // already purchased but going from the back button Instead of testing it's length we are just testing it's value. If the values don't match, the product was NOT purchased. I'll look into this: [allViewControllers removeObjectIdenticalTo:self] funkyness. I'm not familiar with that method but I'll figure out a different approach.
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/16/12 02:00 PM (13 years ago)
My last post is very WRONG. Ignore those changes, I'm trying to figure out the approach here: Just did some tests. I setup two IAP purchase screens with different productID's and uniqueID's in the JSON. I "purchased" the first product. When I visit the first product, I see the IAP purchase screen for a moment, then I'm transitioned to the protected screen. When I visit the second product, I see the IAP purchase screen and it remains there waiting for me to purchase. This confirms it's working as it's designed. Although it appears to be working as expected, I think there's a bit of room for improving it. I don't feel like I should SEE the IAP purchase screen if I'm going to get transitioned to the protected content. Seems to me like an overview of some sorts should hide the IAP stuff while this is figured out so I don't realize what's happening? Dunnno, just a users perspective. Also, the "back" logic is returning me to the IAP purchase screen when I've already purchased it. Weird. Still tinkering....
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/16/12 02:04 PM (13 years ago)
OK, this updated method (still working out some improvements but will need TheMonster's OK on these before changing anything and updating the version). This fixes the "back" issue I ran into where it stops on the IAP screen after purchsing. Overwrite entire method: //view will appear -(void)viewDidAppear:(BOOL)animated{ [super viewWillAppear:animated]; [BT_debugger showIt:self:@"viewWillAppear"]; //flag this as the current screen BT_appDelegate *appDelegate = (BT_appDelegate *)[[UIApplication sharedApplication] delegate]; appDelegate.rootApp.currentScreenData = self.screenData; //setup navigation bar and background [BT_viewUtilities configureBackgroundAndNavBar:self:[self screenData]]; //load the store if we have NOT already done it... if(![self didLoadStore]){ [self loadStore]; } //buy button is hidden until product loads from iTunes Connect... //[buyButton setHidden:TRUE]; //has this device already purchased a product with this productID? NSString *savedPurchasedId = [BT_strings getPrefString:[NSString stringWithFormat:@"purchased_%@", productID]]; [BT_debugger showIt:self:[NSString stringWithFormat:@"SAVED Product ID: %@", savedPurchasedId]]; if([savedPurchasedId length] > 1 && !purchasePageFlag) { // purchased product and hasn't come back from purchase page [BT_debugger showIt:self:@"product already purchased"]; [self goToPurchasedScreen]; } else if ([savedPurchasedId isEqualToString:productID] || purchasePageFlag) // already purchased but going from the back button { NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray: self.navigationController.viewControllers]; [allViewControllers removeObjectIdenticalTo:self]; self.navigationController.viewControllers = allViewControllers; } else { // hasn't purchased yet and not coming back from purchase page [BT_debugger showIt:self:@"product not purchased yet"]; //delay the loading of the image so it does not stall the UI if coming from a URL... [self performSelector:(@selector(loadProductImage)) withObject:nil afterDelay:0.3]; } } That should also fix the "duplicate product" issue you're having. Next, I'll see what improvements I can must up to HIDE the IAP screen when you shouldn't see it anymore. I'll send TheMonster and email to see if I can raise him. I don't mind making some updates but want to make sure he know's what I'm up to :-)
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/16/12 02:04 PM (13 years ago)
Post your findings after using that updated method.
 
Absentia
buzztouch Evangelist
Profile
Posts: 960
Reg: Oct 20, 2011
Alaska
20,600
like
11/16/12 02:48 PM (13 years ago)
Awesome, I don't know how you find time to make such detailed responses but I really appreciate it. I am starting to doubt myself here because, even after pasting your code, I am still having the same two issues. Here's the wierd thing - sometimes it actually does work right - as in, I will succesfully purchase one IAP and the other two will still be locked. I think I've noticed that when the navigation bar bugs out, that is when it seems like all the code goes haywire and all IAPs are magically activated so perhaps these two issues I'm having are somehow related I can't think of any mistakes I could be making - I copy the plugin files directly over and don't tweak them at all (aside from the code you posted above). My productIDs use the format com.jonathanbrake.IAPname
 
David @ buzztouch
buzztouch Evangelist
Profile
Posts: 6866
Reg: Jan 01, 2010
Monterey, CA
78,840
like
11/17/12 03:18 AM (13 years ago)
I've sent an email to TheMonster to try to get some input. I'm leaving of the weekend but will try to jump in if I see something new (or an email). It's very unlikely that you're doing anything "wrong" But..to be sure..what are you testing on? Device? OS version? Etc.
 
Absentia
buzztouch Evangelist
Profile
Posts: 960
Reg: Oct 20, 2011
Alaska
20,600
like
11/17/12 02:29 PM (13 years ago)
ok, thanks again for the help so far I'm testing on an iPhone 4s - iOS 6.0.1
 
Absentia
buzztouch Evangelist
Profile
Posts: 960
Reg: Oct 20, 2011
Alaska
20,600
like
11/19/12 02:17 PM (13 years ago)
Not sure if this will help in any way, but I made a video of me testing out my app - it demonstrates all of the bugs that have been referred to in this thread. I have three IAPs - first I tap on each one to demonstrate that they are all locked, then I purchase one using a test account. When the IAP is complete, you will notice that the back button is gone. I launch one of the quizzes, then go back and the back button has re-appeared. This is when yet another strange bug presents itself - pressing the back button takes me back to the same page that I'm already on! This happens three times before it finally takes me back to the home screen, after which the button seems to work fine - only now, all of the IAP's have been unlocked. This can all be seen taking place in this video - http://www.youtube.com/watch?v=m9HcfE_aSQ4&feature=plcp note: the device being used in the video is an iPad 1, but I have experienced the same exact sequence of bugs on an iPhone 4s as well as on the simulator
 

Login + Screen Name Required to Post

pointerLogin to participate so you can start earning points. Once you're logged in (and have a screen name entered in your profile), you can subscribe to topics, follow users, and start learning how to make apps like the pros.