Android Question [solved] Firebase AppInvites

DonManfred

Expert
Licensed User
Longtime User
I am creating this thread because i am writing a wrap for the Firebase AppInvites and i need some help.

Hopefully one of you know the answer.

In the moment i stuck finding the right import to use in #additionaljar for the Firebase DynamicLinks


The 1st version of the lib is attached including a example project.

If anyone have a hint what i should use in the #additionalar: please share
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
Attached Testproject 06 compiles now without error.

The result with some testsettings:
#- x67, strDynamicLink=com.google.firebase.dynamiclinks.DynamicLink@55a21d2

The expectation was a URL...

B4X:
Sub btnSend_Click
    Log("#-PrepMessage.btnSend_Click")
   
   
    '├
    '├ TODO: Create and send "Dynamic link" via intent
    '├

    ' ─────────────────
    ' This needs to be translated to a B4A Intent "AppInviteInvitation"   
    ' ─────────────────
    ' Info -->    https://github.com/firebase/quickstart-android/blob/master/invites/app/src/main/java/com/google/firebase/quickstart/invites/MainActivity.java#L119-L127
    '
    '                    // [START on_invite_clicked]
    '                    Private void onInviteClicked() {
    '                        Intent intent = new AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title))
    '                                .setMessage(getString(R.string.invitation_message))
    '                                .setDeepLink(Uri.parse(getString(R.string.invitation_deep_link)))
    '                                .setCustomImage(Uri.parse(getString(R.string.invitation_custom_image)))
    '                                .setCallToActionText(getString(R.string.invitation_cta))
    '                                .build();
    '                        startActivityForResult(intent, REQUEST_INVITE);
    '                    }
    '                    // [END on_invite_clicked]
    ' ─────────────────   
   

    ' Some basic testings:
    Dim fbdl As FirebaseDynamicLinks
    fbdl.Initialize("fbdl")
    fbdl.DynamicLinkDomain = "basic4android.de"
    fbdl.setAndroidParameters("http://fallback", 1)
    fbdl.setGoogleAnalyticsParameters("campaign", "content", "medium", "source", "term")
    fbdl.setIosParameters("unknownparameter", "appstoreID", "customscheme", "fallbackurl", "ipadBundleId", "iPadFallbackurl", 1)
    fbdl.setItunesConnectAnalyticsParameters("AffiliateId", "CampaignToken", "ProviderToken")
    fbdl.setSocialMetaTagParameters("description", "imageUrl", "title")
   
    Dim strDynamicLink As String = fbdl.BuildDynamicLink
   
    Log($"#-  x67, strDynamicLink=${strDynamicLink}"$)   
    ' Result from log: #-  x67, strDynamicLink=com.google.firebase.dynamiclinks.DynamicLink@55a21d2




   
    ToastMessageShow("Message sent", True)
 

Attachments

  • fibainvites_06.zip
    18.4 KB · Views: 336
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
btnSend_Click
...
fbdl.buildShortDynamicLink
...
See logpoint x72:

B4X:
    ' TODO [1]: Create "Dynamic link"
    ' some testsettings
    Dim fbdl As FirebaseDynamicLinks
    fbdl.Initialize("fbdl")
    fbdl.DynamicLinkDomain = "basic4android.de"
    fbdl.setAndroidParameters("http://fallback", 1)
    fbdl.setGoogleAnalyticsParameters("campaign", "content", "medium", "source", "term")
    fbdl.setIosParameters("unknownparameter", "appstoreID", "customscheme", "fallbackurl", "ipadBundleId", "iPadFallbackurl", 1)
    fbdl.setItunesConnectAnalyticsParameters("AffiliateId", "CampaignToken", "ProviderToken")
    fbdl.setSocialMetaTagParameters("description", "imageUrl", "title")
   
   
    Dim strDynamicLink As String = fbdl.BuildDynamicLink
    Log($"#-  x67, strDynamicLink=${strDynamicLink}"$)
    '   Result:
    '          from log: #-  x67, strDynamicLink=com.google.firebase.dynamiclinks.DynamicLink@55a21d2

    Log($"#-  x72, trying fbdl.buildShortDynamicLink"$)
    fbdl.buildShortDynamicLink
    '   Result:
    '          from log: #-  x72, trying fbdl.buildShortDynamicLink
    '            com.google.android.gms.tasks.RuntimeExecutionException: com.google.android.gms.common.api.ApiException: Bad Request
    '                at com.google.android.gms.tasks.zzn.getResult(Unknown Source:14)
    '                at de.donmanfred.FirebaseDynamicLinkswrapper$1.onComplete(FirebaseDynamicLinkswrapper.java:55)
    '                at com.google.android.gms.tasks.zzf.run(Unknown Source:23)
    '                at android.os.Handler.handleCallback(Handler.java:789)
    '                at android.os.Handler.dispatchMessage(Handler.java:98)
    '                at android.os.Looper.loop(Looper.java:164)
    '                at android.app.ActivityThread.main(ActivityThread.java:6541)
    '                at java.lang.reflect.Method.invoke(Native Method)
    '                at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
    '                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
    '            Caused by: com.google.android.gms.common.api.ApiException: Bad Request
    '                at com.google.android.gms.internal.zzber.zza(Unknown Source:12)
    '                at com.google.android.gms.internal.zp.zza(Unknown Source:2)
    '                at com.google.android.gms.internal.zu.onTransact(Unknown Source:51)
    '                at android.os.Binder.execTransact(Binder.java:674)
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Bad Request
bad request is a indication that there are wrong parameters...
it looks like some kind of a pointer
it is a DynamicLink Object... I need to revisit the method to return a valid Object (write a wrapper for this object).
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
B4X:
    Dim dynlink As DynamicLink = fbdl.BuildDynamicLink
    Log($"#-  x67, strDynamicLink=${dynlink.Parameters}"$)
    For Each key As String In dynlink.Parameters.Keys
        Log($"#-  x67a, ${key}=${dynlink.Parameters.Get(key)}"$)      
    Next


Parameters is a Map

PD: V0.11 - not yet published (still working on it)
 
Last edited:
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
A bit further.... We need to find out the right parameters we want to set

Attention: Line 63
B4X:
fbdl.DynamicLinkDomain = "xxxx" '  prefix from "xxxx.app.goo.gl"

Dynamic link creation
B4X:
    Dim dynlink As DynamicLink = fbdl.BuildDynamicLink
    Log($"#-  x67, strDynamicLink=${dynlink.Parameters}"$)
    For Each key As String In dynlink.Parameters.Keys
        Log($"#-  x67a, ${key}=${dynlink.Parameters.Get(key)}"$) 
    Next

To create a short dynamic link we need to go another way.

See this new sub signature (and code)

B4X:
Sub fbdl_onComplete(shortinktask As Object)
    Log("#-fbdl_onComplete")
    Dim task As JavaObject = shortinktask
    Do While task.RunMethod("isComplete", Null) = False
        Log($"#-  x67b, sleep(100)"$)
        Sleep(100)
    Loop
    Log($"#-  x67c, task beendet"$)
    'Log("#-  x44, previewLink=" & previewLink)
    'Log("#-  x45, shortLink=" & shortLink)

End Sub

At the end the task is finished but raises the failure event... Probably of the wrong parameters. We need to investigate
 
Last edited:
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
V2.20 fixes it
Great. I was trying to find the imports for hours. Then i decided to post here to maybe get a hint.
Did´nt expect the sdkmanager was the problem

But it is working now. Ok, with issues but we came further ;-)
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
As far as i did understand the documentation (i may be wrong).
To use the deeplink we need to have an App with a packagename which is also a valid https website. Packagename in reverseorder.

for ex. i own the domain basic4android.de
i have a subdomain fbdl in this domain. which results in fbdl.basic4android.de

If i understand it right then i need to have a packagename de.basic4android.fbdl inside my App to allow it google to forward a user to my app.

Any comments on this?
 
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
...which is also a valid https website...?
No.

What might be helping is the thought that we could create a Dynamic Link manually

https://app_code.app.goo.gl/
?link=your_deep_link
&apn=package_name
[&amv=minimum_version]
[&al=android_link]
[&afl=fallback_link]​

According to this we need minimum:
a) the app_code
a) the app's package_name that corresponds to the Firebase project's Settings for this app
b) your_deep_link which holds a well formed URL with 2 parts
b1) the host info you have set up in the Manifest as an intent filter (...<data android:host="yourapp.com"...)
b2) the payload that should be handled by the Activity to which the intentfilter points to​
The other parameters control the behavior if the receiving device doesn't have the app (package_name) installed and optional Analytics settings.​


The link in Firebase's debug mode shows a graphical representation:
https://z3dz3.app.goo.gl/?link=http...m/showdat/data123&apn=b4a.example.fibainv&d=1
 
Upvote 0

fredo

Well-Known Member
Licensed User
Longtime User
How can it help with using the Library?

#16 was only intendet to give additional background information on the DynamicLink structure.


The library would be an "out-of-the-box" solution to build an "AppInviteInvitation"-Intent.

This is how it is used in the Firebase Quickstart example for Invites:
B4X:
    '                    // [START on_invite_clicked]
    '                    Private void onInviteClicked() {
    '                        Intent intent = new AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title))
    '                                .setMessage(getString(R.string.invitation_message))
    '                                .setDeepLink(Uri.parse(getString(R.string.invitation_deep_link)))
    '                                .setCustomImage(Uri.parse(getString(R.string.invitation_custom_image)))
    '                                .setCallToActionText(getString(R.string.invitation_cta))
    '                                .build();
    '                        startActivityForResult(intent, REQUEST_INVITE);
    '                    }
    '                    // [END on_invite_clicked]


The user experience would be an Activity that offers this:

 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
The library would be an "out-of-the-box" solution to build an "AppInviteInvitation"-Intent

The intentbuilder i have implemented. See new lib attached.
Did not tried it. dont know what happen if you call build

B4X:
package de.donmanfred;

import com.google.android.gms.appinvite.AppInviteInvitation;
import com.google.android.gms.appinvite.AppInviteInvitation.IntentBuilder;

import android.content.Intent;
import android.net.Uri;
import anywheresoftware.b4a.BA;
import anywheresoftware.b4a.BA.Events;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.IOnActivityResult;
import anywheresoftware.b4a.objects.collections.List;

@ShortName("AppInviteInvitationBuilder")
//@Permissions(values={"android.permission.INTERNET", "android.permission.ACCESS_NETWORK_STATE"})
@Events(values={"onInvite(invites As List)"})
//@DependsOn(values={"com.google.firebase:firebase-appindexing"})
public class AppInviteInvitationBuilderwrapper  {
    private BA ba;
    private String eventName;
    private IntentBuilder builder;
    private IOnActivityResult ion;
    /*
     * Initialize the HTML-TextView
     */   
    public void Initialize(final BA ba, String EventName, String title) {
        this.eventName = EventName.toLowerCase(BA.cul);
        this.ba = ba;
        builder = new AppInviteInvitation.IntentBuilder(title);

    ion = new IOnActivityResult() {
        
            @Override
            public void ResultArrived(int resultCode, Intent data) {
                ba.Log("ResultArrived("+resultCode+")");
                ba.Log("ResultArrived()");
                List l = new List();
                l.Initialize();
                String[] ids = AppInviteInvitation.getInvitationIds(resultCode, data);
                for (String id : ids) {
                    l.Add(id);
                }
                ba.raiseEventFromDifferentThread(this, null, 0, eventName + "_oninvite", true, new Object[] {l});            
            
            }
        };    
    }
    public void build(){
        ba.startActivityForResult(ion, builder.build());
    }
    public void setMessage(CharSequence invitation_message){
        builder.setMessage(invitation_message);
    }
    public void setDeepLink(String invitation_deep_link){
        builder.setDeepLink(Uri.parse(invitation_deep_link));
    }
    public void setCustomImage(String invitation_custom_image){
        builder.setCustomImage(Uri.parse(invitation_custom_image));
    }
    public void setCallToActionText(CharSequence invitation_cta){
        builder.setCallToActionText(invitation_cta);
    }



}

The Object AppInviteInvitationBuilder is new in this Version...
Attention: New Event onInvite(invites As List)
 
Last edited:
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…