Deep linking, REST authentication with Google/PlayFab

I’m trying to implement PlayFab into my game. I want to be able to register/login with Google (I have registration with email working OK). As far as I can tell, the way to do this with the PlayFab REST interface (via the PlayFabLuaSDK) is for me to have a web page which invites the player to sign in via Google, then authenticates with PlayFab. This bit works OK - I found a PlayFab example here which gave me a useful index.html file.

I can get Defold to open this web page OK with sys.open_url(MY_URL) and PlayFab reponds fine, the response being picked up in the index.html here…

      // Handles response from PlayFab
      function onPlayFabResponse(response, error) {
          if (response) {
              logLine("Response: " + JSON.stringify(response));
              // do something here to get the info back to Defold??
               }
          if (error)
              logLine("Error: " + JSON.stringify(error));
      }

and I assume in Defold I need to be doing something like:
playfab.LoginWithGoogleAccount.flow(request, onSuccessGoogleLogin, onErrorGoogleLogin)
or maybe just picking up the Entity Token details etc from the PlayFab response.

But I’m not at all clear how I actually get that information into Defold. I assume I need to do some kind of deep linking, some function in the javascript to open my app via a URL, but I can’t find any examples or documentation on how this is actually done.

I have added an intent filter to my AndroidManifest as below:

        <activity android:name="com.dynamo.android.DefoldActivity"
                  android:configChanges="orientation|screenSize|keyboardHidden">
            <!-- Intent filter to handle custom URL scheme -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="com.mycompany.mygame"/>
            </intent-filter>
        </activity>

where com.mycompany.mygame matches the package.

That’s about as far as I can work out what to do - I am not clear how I actually get the info which has come back from PlayFab back into Defold.

Are there any examples of this or can anyone advise me how to proceed? I feel like I’m nearly there but am failing to grasp one last step which will hopefully get me there.

Any help very much appreciated, thanks!

Have made some progress, in that the app is now opening via the web page (I needed to make the redirect happen on a button press not just automatically).

I found the iac extension - is that what I need for my game to respond to being reopened?

I’ve not had any luck with it… I added this to my main.init:

local function iac_listener(self, payload, type)
	print("IN IAC LISTENER")

end

function init(self)
	msg.post("@render:", "use_fixed_fit_projection", { near = -1, far = 1 })
	msg.post("#", "show_screen_title")

	print("init main.script")
	iac.set_listener(iac_listener)
end

but the iac_listener function never seems to get called.

Is this what the iac_listener is for? Or am I missing another way to be able to pick up the data I need from PlayFab?

Thanks

this is the relevant bit of the html file that does the authentication and then calls back to the app once PlayFab responds:

      // Handles response from PlayFab
  function onPlayFabResponse(response, error) {
    console.log("onPlayFabResponse called");
    if (response) {
        // ... existing code to process response ...
        var responseData = encodeURIComponent(JSON.stringify(response));
        redirectUrl = "com.MYCOMPANY.MYGAME://auth?response=" + responseData;
        logLine("Response received. Please click the button to return to the app.");
    } else if (error) {
        // ... existing code to process error ...
        var errorData = encodeURIComponent(JSON.stringify(error));
        redirectUrl = "com.MYCOMPANY.MYGAME://auth?error=" + errorData;
        logLine("Error occurred. Please click the button to return to the app.");
    }
}

function redirectToApp() {
    if (redirectUrl) {
        window.location.href = redirectUrl;
    } else {
        alert("No redirect URL available.");
    }
}
.
.
.
.

.... in the HTML:
    <button onclick="redirectToApp();">Return to App</button>

I thought extension-iac was what you would use to make the app open from the webpage (I’m more knowledgeable about iOS than Android, and seeing extension-iac’s info.plist adding the CFBundleURLSchemes key makes me think that).

So, if you were able to redirect to the app without extension-iac, perhaps your changes to AndroidManifest.xml are interfering with extension-iac’s ? Maybe try reverting to the built-in AndroidManifest.xml.

And then I’d be tempted to try the extension-iac example project in isolation, following the usage instructions in main.gui_script, and then adapt that example to work in the context of your webpage,.

1 Like

EDIT - I think my conclusions below are wrong, the next post is probably more sensible (still need help!)

Thanks for that. I hadn’t realised that multiple Android manifests got merged together (in theory) when you add native extensions.

However… what I think my problem is is that the manifests are not being merged together.

Trying out the example code with the IAC library, trying to start the app with adb shell am start -a android.intent.action.VIEW
-c android.intent.category.BROWSABLE
-d “com.defold.iac://testdata”

gives me an Error: Activity not started, unable to resolve Intent

If I take the intent filter snippet from the iac extension Android Manifest and put it into the example’s main Android manifest, then I can start the app fine with the above adb command.

The same applies to my app - removing the intent filter from my manifest and relying on the one in the extension manifest results in the app not opening from the web page. My conclusion is that, in both cases, the info in the extension’s manifest isn’t making it into the final merged manifest file.

So, (maybe!) my question is - is there something I need to do in Defold to ensure that these additional manifests are actually getting merged OK? Or, can I copy and paste the relevent section from the extension manifest into my manifest and expect it to work (I have tried, and it didn’t).

Thanks!

A bit more info…

Trying the demo code for extension-iac again, I’ve created my own AndroidManifest (starting with the one in builtins), adding in this…

        </activity>
        <!-- For IAC Invocations -->
        <activity android:name="com.defold.iac.IACActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:launchMode="singleTask"
            android:exported="false"
            android:configChanges="keyboardHidden|orientation|screenSize">
            <intent-filter>
               <action android:name="android.intent.action.VIEW" />
               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />
               <data android:scheme="{{android.package}}" />
            </intent-filter>
        </activity>

This still won’t start via adb, giving the same error as before (unable to resolve Intent).

If I take that intent-filter snippet and put it into here instead…

    <activity android:name="com.dynamo.android.DefoldActivity"
            android:label="{{project.title}}"
            android:configChanges="fontScale|keyboard|keyboardHidden|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
            android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
            android:screenOrientation="{{orientation-support}}"
            android:exported="true"
            android:launchMode="singleTask">
        <meta-data android:name="android.app.lib_name"
                android:value="{{exe-name}}" />
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
           <action android:name="android.intent.action.VIEW" />
           <category android:name="android.intent.category.DEFAULT" />
           <category android:name="android.intent.category.BROWSABLE" />
           <data android:scheme="{{android.package}}" />
        </intent-filter>
    </activity>

then I can start the app via adb OK (but the IAC listener function doesn’t get called presumably because the intent is being picked up in that different activity).

So, I suspect I was wrong to think the Manifest files are not merging, but I assume something must be wrong with the ‘For IAC Invocations’ activity segment of the Manifest (whether being merged in automatically or pasted in by me).

Can anyone confirm if the example extension-IAC demo works as expected? I must be missing something here but can’t find any solution.

There is this issue so perhaps not
Maybe @AGulev knows the current situation?

No, it should be investigated

@HHH a few of the forks e.g. https://github.com/Car3man/extension-iac have made a minor change to AndroidManifest.xml setting android:exported="true"
It’s not clear what their motivation is for doing so but perhaps try one of those.

You are a superstar!

Thank you so much, that works :slight_smile:

1 Like

Here are the docs on android:exported

So setting it to ‘false’ as in the library would have been stopping other apps from accessing the activity and launching it. The AndroidManifest in the library should be amended as below:

<?xml version="1.0" encoding="utf-8"?>


<uses-sdk android:minSdkVersion="{{android.minimum_sdk_version}}"

android:targetSdkVersion="{{android.target_sdk_version}}" />
    <application>
        
        <!-- For IAC Invocations -->
        <activity android:name="com.defold.iac.IACActivity"
            android:theme="@android:style/Theme.Translucent.NoTitleBar"
            android:launchMode="singleTask"
            android:exported="true"
            android:configChanges="keyboardHidden|orientation|screenSize">
            <intent-filter>
               <action android:name="android.intent.action.VIEW" />
               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />
               <data android:scheme="{{android.package}}" />
            </intent-filter>
        </activity>

    </application>
</manifest>