Search Unity

Google Play games login guide

Discussion in 'iOS and tvOS' started by Lanre, Apr 20, 2015.

  1. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    THIS IS VERY IMPORTANT FOR ALL USING GOOGLE PLAY GAMES SDK FOR iOS

    Good day guys.I submitted my app "Velociti" to the app store, but it got rejected. Screen Shot 2015-04-20 at 11.16.32 AM.png So I filed an appeal, but got rejected again, the apple team saying that I had to use an in-app web view. I spent saturday, sunday, and this morning (monday) trying to fix it in Xcode as I'm not familiar with the iOS environment at all. With help from these links: http://stackoverflow.com/questions/...s-with-out-opening-external-browser-in-iphone and https://code.google.com/p/google-plus-platform/issues/detail?id=900 , I've finally managed to fix it. The instruction on the aforementioned pages are correct but hard to understand for a total noob to Xcode.

    In this post, I'll show you how to get a UIWebView to login to google play directly from your app. Lets begin:-

    1. Build your game from Unity with everything configured as usual (make sure you have configured google play games for iOS in Unity from the menu).

    2. Open the generated XCode project

    3. Right click on "Unity-iPhone" in the top left menu and click "New File".

    4. Select iOS (top left menu) >> Source >> Header File

    5. Name your header file "Application" or anything you want, and make sure your app is selected as a target for the header.

    6. In "Appllication.h", paste this code below "#endif":
    Code (CSharp):
    1. #import <UIKit/UIKit.h>
    2.  
    3. #define ApplicationOpenGoogleAuthNotification @"ApplicationOpenGoogleAuthNotification"
    4.  
    5. @interface Application : UIApplication
    6. - (BOOL)openURL:(NSURL*)url;
    7. @end
    This defines a notification that we are going to use to call the function to open the webview in the app and the method in the Application implementation file that intercepts the google sign in URL.

    7. Next, right click "Unity-iPhone" and select "New File", this time, create an Objective-C file (right next to the header file, it has a big 'm']

    8. Name your Objective-C file "Application" or whatever name you used for the header file (the name must be the same as the header file's name) and select your app as its target.

    9. In "Application.m", paste the following code:
    Code (CSharp):
    1. #import <Foundation/Foundation.h>
    2.  
    3. #import "Application.h"
    4.  
    5. @implementation Application
    6.  
    7. - (BOOL)openURL:(NSURL*)url {
    8.  
    9.     if ([[url absoluteString] hasPrefix:@"googlechrome-x-callback:"]) {
    10.      
    11.         return NO;
    12.      
    13.     } else if ([[url absoluteString] hasPrefix:@"https://accounts.google.com/o/oauth2/auth"]) {
    14.         NSDictionary* dict = [NSDictionary dictionaryWithObject:
    15.                               [NSURL URLWithString:[url absoluteString]]
    16.                                                          forKey:@"url"];
    17.         [[NSNotificationCenter defaultCenter] postNotificationName:ApplicationOpenGoogleAuthNotification object:nil userInfo:dict];
    18.         return NO;
    19.      
    20.     }
    21.  
    22.     return [super openURL:url];
    23. }
    24.  
    25. @end
    26.  
    What this implementation does is that it intercepts the app's call to open safari for the login, the reason why Apple rejects apps like this. It sends a notification to open a UIWebView with the login URL.

    10. Go to the "Info" tab in XCode [if you can't see it, click on "Unity-iPhone" then in the upper-middle, the tab is listed].

    11. Click on the "Bundle Name" entry, a grey "+" sign would appear.

    12. Click the + sign, then in the key blank, type "NSPrincipalClass" exactly; it should change to "Principal Class" if you type it in right.

    13. On the right of "Principal Class" where the key values are, type in "Application" (or the name of your header/implementation file that you created earlier).

    14. Click on Unity-iPhone again, open the drop down list if it isn't opened, navigate to Classes>U> UnityViewControllerBase.h (This is the name of my file as generated by Unity 5, it may be named differently by a different version of Unity, just look for the header file that derives from "UIViewController" like so) Screen Shot 2015-04-20 at 11.40.39 AM.png

    15. Beside "UIViewController", add "<UIWebViewDelegate>". This allows us to use the UniViewControllerBase as the host of the UIWebView and allows it to receive delegate methods.

    16. At the top of the UnityViewControllerBase.h, add the following lines
    Code (CSharp):
    1. #import "GPGSAppController.h"
    2. #import <UnityAppController.h>
    3. #import <GooglePlus/GooglePlus.h>
    4. #import <gpg/ios_support.h>
    17. If the above step causes any errors, make sure you have added the necessary GooglePlayGames SDKs to the project.

    18. Go to "UnityViewBaseController..mm" (The implementation file), scroll down to the "- (void) viewDidAppear" method. Below the method, add the following lines:
    Code (CSharp):
    1. - (void) ShowWeb:(NSNotification *)notification {
    2.     UnityPause(true);
    3.     UIWebView *webview=[[UIWebView alloc]initWithFrame:[[UIScreen mainScreen] bounds]];
    4.     NSURL *pass = [[notification userInfo] valueForKey:@"url"];
    5.     NSURL *nsurl=[NSURL URLWithString:url];
    6.     NSURLRequest *nsrequest=[NSURLRequest requestWithURL:pass];
    7.     webview.backgroundColor = [UIColor whiteColor];
    8.     webview.scalesPageToFit = YES;
    9.     [webview setDelegate:self];
    10.     [webview loadRequest:nsrequest];
    11.     [self.view addSubview:webview];
    12.     webview.delegate = self;
    13. }
    14.  
    15. - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
    16. {
    17.     NSLog(@"Error : %@",error);
    18. }
    19.  
    20. - (void)webViewDidFinishLoad:(UIWebView *)webView
    21. {
    22.     // finished loading, hide the activity indicator in the status bar
    23.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    24. }
    25.  
    26. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    27. {
    28.     if ([[[request URL] absoluteString] hasPrefix:@"com.yusufolokoba.velociti:/oauth2callback"]) {
    29.         [GPPURLHandler handleURL:request.URL sourceApplication:@"com.apple.mobilesafari" annotation:nil];
    30.         [self.navigationController popViewControllerAnimated:YES];
    31.         [webView removeFromSuperview];
    32.         UnityPause(false);
    33.         return NO;
    34.     }
    35.     return YES;
    36. }
    37.  
    This code creates a UIWebView programatically, and contains delegate methods that will check the progress of the user's sign in.

    19. Go back to the viewDidAppear method. Before the end of the method, add the line
    Code (CSharp):
    1. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ShowWeb:) name:@"ApplicationOpenGoogleAuthNotification" object:nil];
    This registers UnityViewControllerBase to receive the login notification.

    20. Build and run. A UIWebView should pop out when you try to sign in now. Because the UIWebView is created programmatically, there is no back or cancel button. No worries, if the user clicks "Cancel" on the webpage, the UIWebView will automatically close and return you to Unity.


    Thanks and have a great day.

    Yusuf.

    NOTE:
    When you replace my bundle id with yours, MAKE SURE THAT IT IS ALL LOWERCASE, else the webview will not close when the user logs in.
     
    Last edited: Jul 8, 2015
    yashpal likes this.
  2. yashpal

    yashpal

    Joined:
    Jul 18, 2014
    Posts:
    14
    hello @yusuf,
    @Lanre ,

    First THANK YOU for this incredible efforts,
    I am also have same problem, my game is also rejected because of same reason.
    I followed your steps.

    at step 18:-
    I don't have "- (void) viewDidAppear" method at "UnityViewBaseController.mm" (The implementation file).
    so i created it and add your code.

    Code (CSharp):
    1. -(void)viewDidAppear:(BOOL)animated
    2. {
    3. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ShowWeb:) name:@"ApplicationOpenGoogleAuthNotification" object:nil];
    4. }
    5.  
    and i get error at "NSURL *nsurl=[NSURL URLWithString:url]; " this line so i deleted it because it not use in the code.
    This is your code.
    Code (CSharp):
    1. - (void) ShowWeb:(NSNotification *)notification {
    2.     UnityPause(true);
    3.     UIWebView *webview=[[UIWebView alloc]initWithFrame:[[UIScreen mainScreen] bounds]];
    4.     NSURL *pass = [[notification userInfo] valueForKey:@"url"];
    5.     NSURL *nsurl=[NSURL URLWithString:url];
    6.     NSURLRequest *nsrequest=[NSURLRequest requestWithURL:pass];
    7.     webview.backgroundColor = [UIColor whiteColor];
    8.     webview.scalesPageToFit = YES;
    9.     [webview setDelegate:self];
    10.     [webview loadRequest:nsrequest];
    11.     [self.view addSubview:webview];
    12.     webview.delegate = self;
    13. }
    This is my code
    Code (CSharp):
    1. - (void) ShowWeb:(NSNotification *)notification {
    2.     UnityPause(true);
    3.     UIWebView *webview=[[UIWebView alloc]initWithFrame:[[UIScreen mainScreen] bounds]];
    4.     NSURL *pass = [[notification userInfo] valueForKey:@"url"];
    5.     //NSURL *nsurl=[NSURL URLWithString:url]; // I commented this because it gives error and not use afterwards in the code.
    6.     NSURLRequest *nsrequest=[NSURLRequest requestWithURL:pass];
    7.     webview.backgroundColor = [UIColor whiteColor];
    8.     webview.scalesPageToFit = YES;
    9.     [webview setDelegate:self];
    10.     [webview loadRequest:nsrequest];
    11.     [self.view addSubview:webview];
    12.     webview.delegate = self;
    13. }
    And I changed url request : "com.yusufolokoba.velociti" to BundleIdOfMyGame.
    Code (CSharp):
    1. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    2. {
    3.     if ([[[request URL] absoluteString] hasPrefix:@"com.yusufolokoba.velociti:/oauth2callback"]) {
    4.         [GPPURLHandler handleURL:request.URL sourceApplication:@"com.apple.mobilesafari" annotation:nil];
    5.         [self.navigationController popViewControllerAnimated:YES];
    6.         [webView removeFromSuperview];
    7.         UnityPause(false);
    8.         return NO;
    9.     }
    10.     return YES;
    11. }

    And at the result
    i get webview open without cancel button. and in full screen.
    It works.

    I will giving my game for review hope it not reject now.
    game crash one time but i did not test it very well. but i think it works.(by the way I am using unity 4.5.0f6. still same steps.)

    Can I put "Back" Or "Cancel" button in view? because it is very good for user experience.
     
    Last edited: Apr 30, 2015
  3. Medhaedu

    Medhaedu

    Joined:
    Mar 30, 2015
    Posts:
    5
    Yes, the Webview is working great, but I still need a cancel button as google login page does not have one. any idea how i can achieve that.
     
  4. p_025

    p_025

    Joined:
    Apr 6, 2013
    Posts:
    22
    Thanks for this, I will have to try this next time I submit a game to crApple using GPGS.
     
  5. eduisfun

    eduisfun

    Joined:
    Apr 2, 2015
    Posts:
    7
    This used to work in another project but now it no longer redirects after logging in and giving access to the app. Any ideas why? I checked the bundleID and URL Scheme (in the Info.plist) and it is the same.
    It currently shows the google search box (google.com) instead of closing the webview and returning to the game.
     
  6. yashpal

    yashpal

    Joined:
    Jul 18, 2014
    Posts:
    14
    Hello eduisfun,

    you need to changed url request : "com.yusufolokoba.velociti" to BundleIdOfYourGame. in the following method.

    Code (CSharp):
    1.  
    2.  
    3. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    4. {
    5.    if ([[[request URL] absoluteString] hasPrefix:mad:"com.yusufolokoba.velociti:/oauth2callback"]) {
    6.        [GPPURLHandler handleURL:request.URL sourceApplication:mad:"com.apple.mobilesafari" annotation:nil];
    7.        [self.navigationController popViewControllerAnimated:YES];
    8.        [webView removeFromSuperview];
    9.         UnityPause(false);
    10.        return NO;
    11.    }
    12.    return YES;
    13. }
    14.  
     
  7. trirom1

    trirom1

    Joined:
    Jun 5, 2014
    Posts:
    14
    Hi,
    I same issue "It currently shows the google search box (google.com) instead of closing the webview and returning to the game." after change "com.yusufolokoba.velociti" --> myBundleId.
    Please help me.
    Note : I got error in this line : #import "GPGSAppController.h" find not found, so I rem it,and run success.
    thanks
     
  8. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    Hi @Lanre Thanks for your support, I actually try to implement your solution, but when the webView appear and I Successful Login With Google, the WebView doesn't close and don't back to the game, only show the Google Default page, can anyone help me?
     
  9. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    That should not happen. I'll check it tomorrow to make sure. Concerning a cancel button, you'll either have to implement a custom UIView in a storyboard then impose it on Unity view when you need it, or make a cancel button and show it on the UIWebView from code. I didn't implement a cancel button because if the user doesn't login or cancels somewhere in the login page process, the UIWebView automatically closes and returns back to the app. This is the same as when the user logs in successfully. Can you please give me an Xcode log of when you successfully login but it doesn't close? Thanks.
     
    JoxieMedina likes this.
  10. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    Ignore the "audios" errors...

    GooglePlayGames.Native.Cwrapper.InternalHooks.InternalHooks_ConfigureForUnityPlugin (HandleRef builder) [0x00000] in <filename unknown>:0

    at audios.changeStateSound (Boolean val) [0x00000] in <filename unknown>:0

    at audios.Update () [0x00000] in <filename unknown>:0

    at Replacements.RemotingServices.CreateClientProxy (System.Type objectType, System.String url, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0

    Replacements.RemotingServices:CreateClientProxy(Type, String, Object[])


    (Filename: currently not available on il2cpp Line: -1)


    2015-07-07 09:46:25.708 Perseverancia[12109:7f13] INFO: Auth operation started: SIGN IN

    2015-07-07 09:46:26.370 Perseverancia[12109:60b] [groovyAPI added to: 0x17e4a6c0]
    //Here the the user logs in successfully
    -> applicationWillResignActive()

    NullReferenceException: A null value was found where an object instance was required.

    at GooglePlayGames.Native.Cwrapper.InternalHooks.InternalHooks_ConfigureForUnityPlugin (HandleRef builder) [0x00000] in <filename unknown>:0

    at audios.changeStateSound (Boolean val) [0x00000] in <filename unknown>:0

    at audios.Update () [0x00000] in <filename unknown>:0

    at Replacements.RemotingServices.CreateClientProxy (System.Type objectType, System.String url, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0

    Replacements.RemotingServices:CreateClientProxy(Type, String, Object[])


    (Filename: currently not available on il2cpp Line: -1)


    -> applicationDidBecomeActive()
    //And here the game enter in a Loop
    NullReferenceException: A null value was found where an object instance was required.
    at GooglePlayGames.Native.Cwrapper.InternalHooks.InternalHooks_ConfigureForUnityPlugin (HandleRef builder) [0x00000] in <filename unknown>:0

    at audios.changeStateSound (Boolean val) [0x00000] in <filename unknown>:0

    at audios.Update () [0x00000] in <filename unknown>:0

    at Replacements.RemotingServices.CreateClientProxy (System.Type objectType, System.String url, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0

    Replacements.RemotingServices:CreateClientProxy(Type, String, Object[])
    ...

    ...
     
  11. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Hey man. As it says, there's a null value somewhere. If the user successfully signs in, there should be INFO: SIGN IN SUCCESSFUL. Here's your culprit:
    Code (CSharp):
    1. NullReferenceException: A null value was found where an object instance was required.
    2.  
    3. at GooglePlayGames.Native.Cwrapper.InternalHooks.InternalHooks_ConfigureForUnityPlugin (HandleRef builder) [0x00000] in <filename unknown>:0
    Add a breakpoint on this line:
    Code (CSharp):
    1.     [GPPURLHandler handleURL:request.URL sourceApplication:mad:"com.apple.mobilesafari" annotation:nil];
    This way we'll know how far the execution goes before encountering the nullrefexception.
     
    JoxieMedina likes this.
  12. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    I just reread your code. It doesn't seem to be a problem with the webview implementation. Try rebuilding from Unity with the default safari login flow and see if it returns to your app, it shouldn't.
     
    JoxieMedina likes this.
  13. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    Hi Lanre, I try you suggest , I rebuild with Unity and the login flow with Safari works fine, but with the webview I still having the same problem :/
     
  14. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Wow. Well I won't be able to pinpoint the problem without the project in Xcode. But I can guide you. Add a breakpoint on the line I asked you to. Tell me if it fires.
     
    JoxieMedina likes this.
  15. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    Hi Lanre, This is my code:
    Code (CSharp):
    1. - (void)viewDidAppear:(BOOL)animated
    2. {
    3.     [super viewDidAppear:animated];
    4.     AppController_SendUnityViewControllerNotification(kUnityViewDidAppear);
    5.     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ShowWeb:) name:@"ApplicationOpenGoogleAuthNotification" object:nil];
    6.  
    7. }
    8. - (void) ShowWeb:(NSNotification *)notification {
    9.     UnityPause(true);
    10.     UIWebView *webview=[[UIWebView alloc]initWithFrame:[[UIScreen mainScreen] bounds]];
    11.     NSURL *pass = [[notification userInfo] valueForKey:@"url"];
    12.    // NSURL *nsurl=[NSURL URLWithString:url];
    13.     NSURLRequest *nsrequest=[NSURLRequest requestWithURL:pass];
    14.     webview.backgroundColor = [UIColor whiteColor];
    15.     webview.frame=CGRectMake(0, 0, 350, 350);
    16.     [webview setDelegate:self];
    17.     [webview loadRequest:nsrequest];
    18.     [self.view addSubview:webview];
    19.     webview.delegate = self;
    20. }
    21.  
    22. - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
    23. {
    24.     NSLog(@"Error : %@",error);
    25. }
    26.  
    27. - (void)webViewDidFinishLoad:(UIWebView *)webView
    28. {
    29.     // finished loading, hide the activity indicator in the status bar
    30.     [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    31. }
    32.  
    33. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    34. {
    35.     if ([[[request URL] absoluteString] hasPrefix:@"com.JeanEspinal.Perseverancia:/oauth2callback"]) {
    36.         [GPPURLHandler handleURL:request.URL sourceApplication:@"com.apple.mobilesafari" annotation:nil];
    37.         [self.navigationController popViewControllerAnimated:YES];
    38.         [webView removeFromSuperview];
    39.         UnityPause(false);
    40.         return NO;
    41.     }
    42.     return YES;
    43. }
    44.  
    And I add the breakpoint on this line
    Code (CSharp):
    1. [GPPURLHandler handleURL:request.URL sourceApplication:@"com.apple.mobilesafari" annotation:nil];
    But never enter on the "if" condition and I don't have logs,
    Code (CSharp):
    1. if ([[[request URL] absoluteString] hasPrefix:@"com.JeanEspinal.Perseverancia:/oauth2callback"]) {
    it seems that is always false
     
  16. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Replace this:
    Code (CSharp):
    1. if ([[[request URL] absoluteString] hasPrefix:@"com.JeanEspinal.Perseverancia:/oauth2callback"]) {
    With this:
    Code (CSharp):
    1. if ([[[request URL] absoluteString] hasPrefix:@"com.jeanespinal.perseverancia:/oauth2callback"]) {
    Tell me if it works.
     
    JoxieMedina likes this.
  17. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    Yes it works, Thank you very much,but I Still having a loop with this:

    Code (CSharp):
    1. NullReferenceException: A null value was found where an object instance was required.
    2.   at GooglePlayGames.Native.Cwrapper.InternalHooks.InternalHooks_ConfigureForUnityPlugin (HandleRef builder) [0x00000] in <filename unknown>:0
    3.   at audios.changeStateSound (Boolean val) [0x00000] in <filename unknown>:0
    4.   at audios.Update () [0x00000] in <filename unknown>:0
    5.   at Replacements.RemotingServices.CreateClientProxy (System.Type objectType, System.String url, System.Object[] activationAttributes) [0x00000] in <filename unknown>:0
    6. Replacements.RemotingServices:CreateClientProxy(Type, String, Object[])
    7. (Filename: currently not available on il2cpp Line: -1)
    The game always Log in, and I don't know what is the problem. but doesn't matters what, the game works and Thanks again.
     
  18. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    Hey man, it's my fault. I encountered the same problem but I forgot all about it. The domain identifier must be all lowercase. As for your error, it could be from your "audios" script. Take care.
     
    JoxieMedina likes this.
  19. trirom1

    trirom1

    Joined:
    Jun 5, 2014
    Posts:
    14
  20. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    there should be google play games frameworks which you link to your xcode project. unlink all then relink them and tell me if that works
     
  21. trirom1

    trirom1

    Joined:
    Jun 5, 2014
    Posts:
    14
    Hi Lanre, thank for your help.
    I try unlink and relink but this error still happen, I rem this line, it worked normal, I can signing google play, enter leaderboard it show top user and stuck at this,I can't back into game(it not happen if I login by safari)
    and log:
    Thank you :)
    INFO: Auth operation started: SIGN IN

    2015-07-09 21:58:22.760 [UI] (Error) __27+[GPGManager registerFonts]_block_invoke:[main] Unable to load font (RobotoCondensed-Italic), error ((null))

    2015-07-09 21:58:22.761 [UI] (Error) __27+[GPGManager registerFonts]_block_invoke:[main] Unable to load font (Roboto-Light), error ((null))

    2015-07-09 21:58:22.761 [UI] (Error) __27+[GPGManager registerFonts]_block_invoke:[main] Unable to load font (Roboto-Medium), error ((null))

    2015-07-09 21:58:22.761 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [welcome_back_notification] in bundle [(null)]

    You've successfully logged in

    After I enter show Leaderboard


    System.Collections.Generic.Transform`1:EndInvoke(IAsyncResult)

    UnityEngine.Debug:Internal_Log(Int32, String, Object)

    UnityEngine.Debug:Log(Object)

    GooglePlay:<OnMouseDown>m__A9(Boolean)

    <PrivateImplementationDetails>:.ctor()

    GooglePlayGames.Native.Cwrapper.AchievementManager:AchievementManager_FetchResponse_GetData(HandleRef)

    GooglePlayGames.Native.<InvokeCallbackOnGameThread>c__AnonStoreyD:<>m__1B()

    System.Action:Invoke()

    OnePF.OpenIAB_iOS:enableDebugLogging(Boolean, String)

    GooglePlayGames.OurUtils.PlayGamesHelperObject:<Update>m__F(Action)

    <PrivateImplementationDetails>:.ctor()

    OnePF.OpenIAB_iOS:enableDebugLogging(Boolean, String)

    <PrivateImplementationDetails>:.ctor()

    GooglePlayGames.OurUtils.PlayGamesHelperObject:Update()

    System.Collections.Generic.Transform`1:EndInvoke(IAsyncResult)


    (Filename: /Users/builduser/buildslave/unity/build/artifacts/iPhonePlayer-armv7-il2cppGenerated/UnityEngineDebug.cpp Line: 56)


    HandleAdLoaded event received.

    System.Collections.Generic.Transform`1:EndInvoke(IAsyncResult)

    UnityEngine.Debug:Internal_Log(Int32, String, Object)

    UnityEngine.Debug:Log(Object)

    UnityEngine.MonoBehaviour:print(Object)

    Ads:HandleAdLoaded(Object, EventArgs)

    <PrivateImplementationDetails>:.ctor()

    GooglePlayGames.Native.Cwrapper.AchievementManager:AchievementManager_FetchResponse_GetData(HandleRef)

    GoogleMobileAds.Api.BannerView:GoogleMobileAds.Common.IAdListener.FireAdLoaded()

    OnePF.OpenIAB_iOS:enableDebugLogging(Boolean, String)

    GoogleMobileAds.iOS.IOSBannerClient:AdViewDidReceiveAdCallback(IntPtr)

    GoogleMobileAds.iOS.IOSBannerClient:DestroyBannerView()


    (Filename: /Users/builduser/buildslave/unity/build/artifacts/iPhonePlayer-armv7-il2cppGenerated/UnityEngineDebug.cpp Line: 56)


    2015-07-09 22:00:00.891 ZombieRun[228:15119] Failed to load font: Error Domain=com.apple.CoreText.CTFontManagerErrorDomain Code=101 "The operation couldn’t be completed. (com.apple.CoreText.CTFontManagerErrorDomain error 101 - Could not register the font file(s))" UserInfo=0x170e65680 {NSDescription=Could not register the font file(s), CTFontManagerErrorFontURLs=(

    "file:///private/var/mobile/Containers/Bundle/Application/668E0D7D-CC13-448D-A153-C599F3CF0FD2/ZombieRun.app/GoogleKitCore.bundle/Roboto-Medium.ttf"

    )}

    Jul 9 22:00:00 iPhone ZombieRun[228] <Error>: CGContextSetFillColorWithColor: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

    Jul 9 22:00:00 iPhone ZombieRun[228] <Error>: CGContextSetStrokeColorWithColor: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

    Jul 9 22:00:00 iPhone ZombieRun[228] <Error>: CGContextGetCompositeOperation: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

    Jul 9 22:00:00 iPhone ZombieRun[228] <Error>: CGContextSetCompositeOperation: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

    Jul 9 22:00:00 iPhone ZombieRun[228] <Error>: CGContextFillRects: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

    Jul 9 22:00:00 iPhone ZombieRun[228] <Error>: CGContextSetCompositeOperation: invalid context 0x0. This is a serious error. This application, or a library it uses, is using an invalid context and is thereby contributing to an overall degradation of system stability and reliability. This notice is a courtesy: please fix this problem. It will become a fatal error in an upcoming update.

    2015-07-09 22:00:01.020 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_cell_header_social] in bundle [(null)]

    2015-07-09 22:00:01.020 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_cell_header_public] in bundle [(null)]

    2015-07-09 22:00:01.020 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_time_scope_all_time] in bundle [(null)]

    2015-07-09 22:00:01.520 ZombieRun[228:15119] Unbalanced calls to begin/end appearance transitions for <GPGLauncherWindowRootViewController: 0x144782440>.

    2015-07-09 22:00:04.399 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.400 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.400 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.400 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.400 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.400 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.400 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.401 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.402 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.402 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.402 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.402 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.402 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.403 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.418 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.419 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.419 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.419 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.419 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.419 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.419 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_unranked_button] in bundle [(null)]

    2015-07-09 22:00:04.419 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.420 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_time_scope_all_time] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.440 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_entry_me] in bundle [(null)]

    2015-07-09 22:00:04.442 [Core] (Error) +[GPGLocalization stringForId:]:[main] Failed to find string for [leaderboard_time_scope_all_time] in bundle [(null)]
     
  22. trirom1

    trirom1

    Joined:
    Jun 5, 2014
    Posts:
    14
    Sorry, this issue were fixed, I got wrong when add library.
    But, I don't know why I alway error when have this line #import "GPGSAppController.h" --> file not found.
    I rem it, and everything ok.
    It worked.
    Note : anyone pass review by Apple ?. In first time when logging account, I must fill google account and Password but not have button cancel. That mean I must login it and can't back to game, this case can reject by apple ?
    Thank :)
     
  23. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    I did. I made this implementation for my app Velociti (I took it off the app store) and Apple approved it. As I've said, if the user cancels their sign in somewhere in the login page, the UIWebView will close, thus removing the need for a cancel button.
     
    trirom1 likes this.
  24. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    My Game still being rejected :( :( :(

     
  25. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    You should make the user sign in to Google on the first app launch, not as late as when they click on leaderboard. Secondly, they didn't complain about a close for me. You can either send a petition to App Review telling them that the window can in fact be closed if the user cancels during the login process; or you could implement a cancel button from code.
     
  26. turkenh

    turkenh

    Joined:
    May 14, 2015
    Posts:
    2
    For those who need a back button, I want to share my solution:

    1. In UnityViewControllerBase.h
    Code (CSharp):
    1. @interface UnityViewControllerBase : UIViewController<UIWebViewDelegate>
    2. {
    3.     + UIWebView* myWebview;
    4.     + UIButton *backButton;
    5. }
    2. In UnityViewControllerBase.mm
    Code (CSharp):
    1. - (void) ShowWeb:(NSNotification *)notification {
    2.     UnityPause(true);
    3.     CGRect screenRect = [[UIScreen mainScreen] bounds];
    4.     CGFloat screenWidth = screenRect.size.width;
    5.     CGFloat screenHeight = screenRect.size.height;
    6.     CGFloat buttonHeight = screenHeight/20;
    7.  
    8.     CGRect webFrame = CGRectMake(0, buttonHeight, screenWidth, screenHeight-buttonHeight);
    9.     myWebview =[[UIWebView alloc]initWithFrame:webFrame];
    10.     NSURL *pass = [[notification userInfo] valueForKey:@"url"];
    11.     //NSURL *nsurl=[NSURL URLWithString:url];
    12.     NSURLRequest *nsrequest=[NSURLRequest requestWithURL:pass];
    13.     myWebview.backgroundColor = [UIColor whiteColor];
    14.     myWebview.scalesPageToFit = YES;
    15.     [myWebview setDelegate:self];
    16.     [myWebview loadRequest:nsrequest];
    17.  
    18.     backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    19.     [backButton addTarget:self
    20.                action:@selector(closeWebView:)
    21.      forControlEvents:UIControlEventTouchUpInside];
    22.     [backButton setTitle:@"Cancel Login & Go Back to the Game" forState:UIControlStateNormal];
    23.     backButton.frame = CGRectMake(0, 0, screenWidth, buttonHeight);
    24.     [backButton setBackgroundColor:[UIColor whiteColor]];
    25.  
    26.     myWebview.delegate = self;
    27.  
    28.     [self.view addSubview:backButton];
    29.     [self.view addSubview:myWebview];
    30.  
    31.  
    32.  
    33.    // [self.view addSubview:button];
    34. }
    35. -(void)closeWebView:(id)sender {
    36.     [GPPURLHandler handleURL:[NSURL URLWithString:@"com.ht.wordcrushgame:/oauth2callback?error"] sourceApplication:@"com.apple.mobilesafari" annotation:nil];
    37.     [self.navigationController popViewControllerAnimated:YES];
    38.     [backButton removeFromSuperview];
    39.     [myWebview removeFromSuperview];
    40.     UnityPause(false);
    41. }
    42. - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    43. {
    44.     if ([[[request URL] absoluteString] hasPrefix:@"com.ht.wordcrushgame:/oauth2callback"]) {
    45.         NSLog(@"%@",request.URL);
    46.         [GPPURLHandler handleURL:request.URL sourceApplication:@"com.apple.mobilesafari" annotation:nil];
    47.         [self.navigationController popViewControllerAnimated:YES];
    48.         [webView removeFromSuperview];
    49.         [backButton removeFromSuperview];
    50.         UnityPause(false);
    51.         return NO;
    52.     }
    53.     return YES;
    54. }
    What I got with the above code is as follows:
     
    JoxieMedina and yashpal like this.
  27. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    Thank's @turkenh for share your solution, but my app still being rejected, by this - Screens were crowded or laid out in a way that made it difficult to complete tasks. I think i have this problem because i have landscape mode for default in my game, the webview is showing too small in iPad.
    Can anyone help me to implement the solution of @Lanre with this solution for webview http://www.touch-code-magazine.com/showing-a-popup-window-in-ios6-modernized-tutorial-code-download/ ?? I tried but I don't have experience with Objetive -C and can't make it work :/
     
  28. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    @JoxieMedina why don't you try the easier solution of setting your orientation to portrait then changing it to landscape after the login?
     
    JoxieMedina likes this.
  29. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    Thanks @Lanre , I gonna try this one and I give you my feedback :D
     
  30. JoxieMedina

    JoxieMedina

    Joined:
    Apr 3, 2014
    Posts:
    9
    I tried the solution of Lanre, but no luck , I can't made the change of Landscape to Portrait, I have a limited knowledge of Objective-c and I don't understand the generated project of Unity3d.
    I try with the Orientation Support script but the game is falling in a loop with the orientation of the WebView. @Lanre, can you give me a example for how to do this correctly?
     
  31. Lanre

    Lanre

    Joined:
    Dec 26, 2013
    Posts:
    3,973
    This code should be done in Unity. Go to Project Settings > Player > And change orientation to portrait only. Then create a C# or JS script and name it whatever you like, probably "LoginFlowOrientation". Attach it to an empty gameObject in your first scene.
    Code (CSharp):
    1. function Start () : IEnumerator {
    2. yield WaitForSeconds(5f); //Or an arbitrary amount of time till when you reckon the login flow pops up
    3.  
    4. //Then set the rotations you'd like to allow
    5. Screen.autorotateToLandscapeLeft = true;
    6. Screen.autorotateToLandscapeRight = true;
    7.  
    8. //Apply rotation
    9. Screen.orientation = ScreenOrientation.AutoRotation;
    10. }
    If there's an intermediate scene between the login flow and the game, then you can change the start() to a void, remove the yield, and place the script in the game scene.