Unity: Receive Firebase Short Dynamic Link in DynamicLinkReceived callback event - firebase

I would like to use Firebase Dynamic Links for Unity (Android/iOS) so users can invite friends and be rewarded with.
Each user gets a different Short Dynamic Link in the form of https://test.page.link/abcd
The user can share this Short DynamicLink with friends.
When the invited friend comes into the app, this callback is called.
private void OnDynamicLink(object sender, EventArgs args) {
var dynamicLinkEventArgs = args as ReceivedDynamicLinkEventArgs;
Debug.LogFormat("Received dynamic link {0}",
dynamicLinkEventArgs.ReceivedDynamicLink.Url.OriginalString);
}
Unfortunately, I only get back the base link that was necessary to create the short dynamic link.
Received dynamic link https://www.example.com/referral?xxxxxxxxxx
I get an additional native output in my iOS app:
IOSNative::Native->Unity callback data:
{"m_EventName":"continueUserActivity","m_Data":"https://test.page.link/?link=https://www.example.com/referral?xxxxxxxxxx&apn=de.test.testapp&isi=123456789&ibi=de.test.testapp&cid=1579347010984123886&_osl=https://test.page.link/abcd&_fpb=AB6327276CFGHT==&_cpt=cpit&_iumenbl=1&_iumchkactval=1&_plt=2076&_uit=2692&_cpb=1"}
2020-01-14 15:30:20.455009+0100 ambassador[315:8406]
IOSNative::Native->Unity callback data:
{"m_EventName":"applicationDidBecomeActive","m_Data":""}
Now my question is how do I get the generated short dynamic link that I have shared with a friend in OnDynamicLink callback( https://test.page.link/abcd)?
I need the value behind the parameter "&_osl" as seen in additional native output. But I only get the Base Url back in Unity (https://www.example.com/referral?xxxxxxxxxx).

My solution at the end was to shorten the BaseLink with the help of DynamicLinks.GetShortLinkAsync.
//unescape url
baseLink = UnityEngine.Networking.UnityWebRequest.UnEscapeURL(baseLink);
var components = new DynamicLinkComponents(
// The base Link.
new Uri(baseLink),
// The dynamic link URI prefix.
domainUriPrefix) {
IOSParameters = new IOSParameters(PackageName) {
AppStoreId = "XXXXXXXXX"
},
AndroidParameters = new AndroidParameters(PackeName)
};
string inviteLink = string.Empty;
await DynamicLinks.GetShortLinkAsync(components, options).ContinueWith((task) => {
if (task.IsCanceled) {
Debug.LogError("GetShortLinkAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("GetShortLinkAsync encountered an error: " + task.Exception);
return;
}
// Short Link has been created.
inviteLink = task.Result.Url.ToString();
});

Related

Firebase Auth with unity creates new user in every start

I'm using firebase anonymous authantication for my unity project.
As i always did when project is started i'm sending request to firebase for authantication,
but on my last project (which uses firebase sdk 6.16.0) my request creates new user everytime.
Here is some code about how i'm sending my request
Firebase.Auth.FirebaseAuth auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.SignInAnonymouslyAsync().ContinueWith((task =>
{
if (task.IsCanceled)
{
Debug.Log("task cancelled");
return;
}
if (task.IsFaulted)
{
Debug.Log("task cancelled");
return;
}
if (task.IsCompleted)
{
Firebase.Auth.FirebaseUser userr = task.Result;
firebaseUserId = userr.UserId;
Debug.Log("firebaseUserId");
Debug.Log(firebaseUserId);
//every opening returns new uniq id here.
}
}));
On firebase authantication panel i only activated anonymous login. any suggestions?
Or is there any way to downgrade unity firebase version? i've tried to import old version which i was using on my last game (sdk 6.15.2) but there is some errors on resolver.
Basically, every time you call SignInAnonymouslyAsync you'll create a new user and the last one will be basically lost (it's more or less a random hash - anonymous as it's name suggests).
I'll typically do something like:
using System;
using Firebase.Auth;
using UnityEngine;
using UnityEngine.Events;
public class Login : MonoBehaviour
{
public UnityEvent OnSignInFailed = new UnityEvent();
public UserSignedInEvent OnUserSignedIn = new UserSignedInEvent();
public async void TriggerLogin()
{
var auth = FirebaseAuth.DefaultInstance;
var user = auth.CurrentUser;
if (user == null)
{
try
{
user = await auth.SignInAnonymouslyAsync();
}
catch (Exception e)
{
Debug.LogException(e);
OnSignInFailed.Invoke();
return;
}
}
// user definitely should not be null!
if (user == null)
{
OnSignInFailed.Invoke();
Debug.LogWarning("User still null!?");
return;
}
var userName = user.UserId;
OnUserSignedIn.Invoke(userName);
Debug.Log($"Logged in as {userName}");
}
[Serializable]
public class UserSignedInEvent : UnityEvent<string>
{
}
}
Note that for this code snippet, TriggerLogin is a public method so I can chain it off of a UnityEvent in the Unity editor.
Try and Put it some kind of check to find if used is already logged in. If yes, then do a silent login, if no then use anonymous login.
Currently you are straightaway logging in user even if they logged in last time they opened the Application.
Try this link: https://github.com/firebase/quickstart-unity/issues/266#issuecomment-447981995

MessagingCenter.Subscribe in not listening to outsider messages?

I'm loading the page's data in the OnAppearing method, but this causes loading data in situations where it doesn't change, like calling PopupAsync() from another page. so I thought the messaging center would help. I made a flag field in the page, and subscribed to any message coming from outside to decide whether to update data or not,
for example this from the MenuViewModel (when the user first opens the page, so I need to load data):
var p = new FeedbackListPage();
MessagingCenter.Send(this, "loadData", "1");
await Navigation.PushAsync(p);
and in the FeedbackListPage's constructor:
InitializeComponent();
BindingContext = vm = new FeedbackViewModel(Navigation);
MessagingCenter.Subscribe<string>(this, "loadData", ( _loadData) =>
{
loadDataStr = _loadData;
});
and in the OnAppearing:
protected override void OnAppearing()
{
base.OnAppearing();
if (loadDataStr=="1")
vm.OnLoadFeedbacks();
}
the problem is that the Subscribe's action is never called!
Solution:
The API for MessagingCenter:
1.Subscribe<TSender> (object subscriber, string message, Action<TSender> callback, TSender source = null)
2.Subscribe<TSender, TArgs> (object subscriber, string message,Action<TSender, TArgs> callback, TSender source = null)
So, if you want to pass an Argument using MessageCenter, you should define both Sender and Args:
MessagingCenter.Subscribe<MainPage,string>(this, "loadData", (sender,_loadData) =>
{
loadDataStr = _loadData;
});
Refer: messaging-center
You can try the following:
use MessagingCenter.Send to send the signal when you want to update the data from any page and then in your ViewModel's constructor use MessagingCenter.Subscribe to perform the needed action
Send:
MessagingCenter.Send<namespace.App>((namespace.App)Xamarin.Forms.Application.Current, "update");
Subscribe:
MessagingCenter.Subscribe<namespace.App>((namespace.App)Application.Current, "update", (sender) => {
// update - get data
});

View event details in Firebase

I am sending app usage analytics events to Fabric and Firebase. Together with the event, I am also sending another value (an example event type is font_selection and the value I pass is which font the user selects - this is a number that tells me which font was used). I was using Fabric events and I could see which fonts were being used more or less when I selected the font_selection event (I could see numbers for each different font).
Since the Fabric functionality is being moved to Firebase, I started checking the Analytics section in Firebase. Unfortunately I cannot find the above information in Firebase > Analytics > Events. I can see the event, font_selection but when I click on it I do not get the additional information I used to get in Fabric. Is there something I am missing or has this additional information been removed from Firebase?
This is still an issue for me. Here is how I'm sending the event into Firebase:
protected void Report(string id, Severity severity, string message = null, Exception exception = null)
{
try
{
var processedId = id ?? severity.ToString().ToLowerInvariant();
var values = new Dictionary<string, string>();
values.Add("severity", severity.ToString().ToLowerInvariant());
if (!string.IsNullOrWhiteSpace(message))
{
values.Add("message", message);
}
if (exception != null)
{
values.Add("exception", exception.Message);
values.Add("trace", exception.StackTrace);
}
SendEvent(values, processedId);
}
catch
{
// do nothing.
}
}
protected override void SendEvent(Dictionary<string, string> eventData, string id)
{
var firebaseAnalytics = FirebaseAnalytics.GetInstance(Android.App.Application.Context);
var bundle = new Android.OS.Bundle();
foreach(var pair in eventData)
{
bundle.PutString(pair.Key, pair.Value);
}
firebaseAnalytics.LogEvent(id, bundle);
}
During runtime, I call this successfully and I can see these event popping up in Firebase console:
But how do I display the rest of the properties that I have bundled with it? Here is what the console shows me in events:
I feel like I must be using it wrong or something. There is no UI to shows me a simple chronologically sorted table with events as they came in with properties they came with. I frankly don't understand what good is this tool to me.

Firebase dynamic link support custom parameters?

I am writing a App for a Open Source Conference.
Originally each attendees will receive different link via email or SMS like
https://example.com/?token=fccfc8bfa07643a1ca8015cbe74f5f17
then use this link to open app, we can know the user is which attendee by the token.
Firebase release a new feature Dynamic Links in I/O 2016, it provide better experience for users.
I had try that, but I can't find any way to pass the custom parameters (the token) in dynamic links, how to use the same link with different parameters to my users?
Thanks.
I don't think you can use the short url:
https://<my app>.app.goo.gl/Gk3m
unless you create one for each user, but you can use the long url:
https://<my app>.app.goo.gl/?link=https://example.com/?token=fccfc8bfa07643a1ca8015cbe74f5f17 ...(add other parameters as needed)
and set new token for each user.
I assume you generate the tokens automatically. In that case you can use this to shorten the links.
1) From https://console.firebase.google.com/ (no need for custom parameter here.)
2) Create link somewhere, f.e. on your confluence page (here we add our parameter):
https://PROJECTNAME.page.link/?link=https://PROJECTNAME.page.link/LINKNAME?PARAMETER=1&ofl=https://www.PROJECTNAME.com/
PARAMETER is your custom parameter.
ofl is a link where to go if click the link from another platform (PC, Mac).
3) Getting link data from android project Kotlin code:
Firebase.dynamicLinks
.getDynamicLink(intent)
.addOnSuccessListener { pendingDynamicLinkData ->
val parameter: String =
pendingDynamicLinkData?.link?.getQueryParameter("PARAMETER").orEmpty()
}
If you want to use dynamic links with custom arguments with REST, here is an example of a payload:
{
"dynamicLinkInfo": {
"dynamicLinkDomain": "example.app.goo.gl",
"link": "http://someurl.com?my_first_param=test&my_second_param=test2"
},
"suffix": {
"option":"UNGUESSABLE"
}
}
Make sure your remove 'https://' from your dynamicLinkDomain
Julien
Case A. If you want the short link to expand to a link with multiple parameters:
In the part where you setup a dynamic link, any parameter you append to the deep link URL will go on all platforms (web, iOS, android)
Case B. If you want to use dynamic parameters, you should use the api to create a short link
see documentation
Now you can create short links using the Firebase SDK through the FirebaseDynamicLinks.getInstance().createDynamicLink():
https://firebase.google.com/docs/dynamic-links/android/create
Sample code:
Task shortLinkTask = FirebaseDynamicLinks.getInstance().createDynamicLink()
.setLink(Uri.parse("https://example.com/"))
.setDynamicLinkDomain("abc123.app.goo.gl")
// Set parameters
// ...
.buildShortDynamicLink()
.addOnCompleteListener(this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if (task.isSuccessful()) {
// Short link created
Uri shortLink = task.getResult().getShortLink();
Uri flowchartLink = task.getResult().getPreviewLink();
} else {
// Error
}
}
});
Create a dynamic link
Go to link details
Copy the long dynamic link and add your parameter in the link parameter of the URL, e.g., PARAMETER=132323
https://link.projectname.com/?link=https://link.projectname.com/LINK?PARAMETER=132323&apn=com.projectname.app&afl=https://link.projectname.com/LINK
1 First Change your Dynamic Link in firebase console from http://exampleandroid/test to http://exampleandroid/test?data 2. You send the query paramter data with this
DynamicLink dynamicLink = FirebaseDynamicLinks.getInstance().createDynamicLink()
// .setLink(dynamicLinkUri)
.setLink(Uri.parse("http://exampleandroid/test?data=dsads"))
.setDomainUriPrefix("https://App_Name.page.link")
// Open links with this app on Android
.setAndroidParameters(new DynamicLink.AndroidParameters.Builder().build())
// Open links with com.example.ios on iOS
.setIosParameters(new DynamicLink.IosParameters.Builder("com.appinventiv.ios").build())
.buildDynamicLink();
dynamicLinkUri = dynamicLink.getUri();
You can add extra parameter to your link to generate Short URL from Firebase.
Here I given example of Short URL generation using Firebase API.
Here ServiceRequestHelper(this).PostCall is my generic class to make API request
String url = "https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=YOUR_KEY";
try {
PackageManager manager = this.getPackageManager();
PackageInfo info = manager.getPackageInfo(this.getPackageName(), 0);
JSONObject jsonObject = new JSONObject();
JSONObject androidInfoObject = new JSONObject();
androidInfoObject.put("androidPackageName", getApplicationContext().getPackageName());
androidInfoObject.put("androidMinPackageVersionCode",String.valueOf(info.versionCode));
JSONObject iosInfoObject = new JSONObject();
iosInfoObject.put("iosBundleId", "tettares.Test_ID");
JSONObject dynamicLinkInfoObj = new JSONObject();
dynamicLinkInfoObj.put("dynamicLinkDomain", "wgv3v.app.goo.gl");
dynamicLinkInfoObj.put("link", "https://test.in/?UserId=14&UserName=Naveen"); // Pass your extra paramters to here
dynamicLinkInfoObj.put("androidInfo", androidInfoObject);
dynamicLinkInfoObj.put("iosInfo", iosInfoObject);
JSONObject suffixObject = new JSONObject();
suffixObject.put("option" , "SHORT");
jsonObject.put("dynamicLinkInfo", dynamicLinkInfoObj);
jsonObject.put("suffix", suffixObject);
Log.d("JSON Object : " , jsonObject.toString());
new ServiceRequestHelper(this).PostCall(url, jsonObject, false, new CallBackJson() {
#Override
public void done(JSONObject result) throws JSONException {
try {
if (result.has("shortLink")) {
DEEP_LINK_URL = result.getString("shortLink"); }
} catch(Exception e)
{
e.printStackTrace();
}
}
});
} catch (JSONException | PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
In Your Receiving Activity:
boolean autoLaunchDeepLink = false;
AppInvite.AppInviteApi.getInvitation(mGoogleApiClient, this, autoLaunchDeepLink)
.setResultCallback(
new ResultCallback<AppInviteInvitationResult>() {
#Override
public void onResult(#NonNull AppInviteInvitationResult result) {
if (result.getStatus().isSuccess()) {
// Extract deep link from Intent
Intent intent = result.getInvitationIntent();
String deepLink = AppInviteReferral.getDeepLink(intent);
// Handle the deep link. For example, open the linked
// content, or apply promotional credit to the user's
// account.
// [START_EXCLUDE]
// Display deep link in the UI
Log.d(TAG, "deeplink URL: " + deeplink); // Here you get https://test.in/?UserId=14&UserName=Naveen
// [END_EXCLUDE]
} else {
Log.d(TAG, "getInvitation: no deep link found.");
}
}
});
I tried all above but none work. So I think you should change the link http://example.com/?userid=123tohttp://example.com/userid/123
No need of all the hustle
Don't shorten the url if you want to pass parameters
Write the links like this.
//APP_CODE is firebase link
String link = "https://APP_CODE.app.goo.gl/?refferer=" + userId;
Intent intent = new AppInviteInvitation.IntentBuilder(getString(R.string.invitation_title))
.setMessage(getString(R.string.invitation_custom_message)))
.setDeepLink(Uri.parse(link))
.setCustomImage(Uri.parse(getString(R.string.invitation_custom_image)))
.setCallToActionText(getString(R.string.invitation_cta))
.build();
startActivityForResult(intent, REQUEST_INVITE);
For web apps, which generating dynamic links..
const data = {
dynamicLinkInfo: {
domainUriPrefix: 'subdomain.page.link',
link: url,
},
suffix: {
option: 'SHORT'
}
};
return fetch(`https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=${environment.firebaseConfig.apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
}).then(res => res.json()).then(response => response.shortLink).catch(console.error);

Windows Phone 8.1 universal app, Navigate to a particular on tapping of receive Push Notification

I am sending Push notification from Azure Notification hub. I want to navigate to particular page on tap of received Toast Push Notification. I am receiving Push notification but unable to navigate to a particular page.
Here is my insert code:
function insert(item, user, request) {
var payload = '<?xml version="1.0" encoding="utf-8"?><toast><visual>' +
'<binding template="ToastText01"> <text id="1">' +
item.subject + '</text></binding></visual></toast>';
request.execute({
success: function () {
// If the insert succeeds, send a notification.
push.wns.send(null, payload, 'wns/toast', {
success: function (pushResponse) {
console.log("Sent push:", pushResponse);
request.respond();
},
error: function (pushResponse) {
console.log("Error Sending push:", pushResponse);
request.respond(500, { error: pushResponse });
}
});
}
});
}
Can any one please help?
There is a number of steps here and you didn't give very much detail on your problem. I'll try to explain the concept in full of anyone who might need the whole thing. Be sure you've set up all the steps in this article first: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-javascript-backend-windows-phone-get-started-push/
First, you need to send the push notification with the page you want to load. So let's say you have a page that shows some details about an item. When you get a push notification, it automatically opens up that item. You could send a payload like:
var payload = '<?xml version="1.0" encoding="utf-8"?><toast><visual>' +
'<binding template="ToastText01"> <text id="1">' +
item.id + '</text></binding></visual></toast>';
Then you need to respond to the push notification. You can see the documentation page for this here: https://msdn.microsoft.com/en-us/library/hh221550.aspx
Your set up code would look something like this:
ShellToastNotificationReceived +=
new EventHandler<NotificationEventArgs>(httpChannel_ShellToastNotificationReceived);
public static HttpNotificationChannel CurrentChannel { get; private set; }
// This is from the tutorial linked in the first paragraph
private void AcquirePushChannel()
{
CurrentChannel = HttpNotificationChannel.Find("MyPushChannel");
if (CurrentChannel == null)
{
CurrentChannel = new HttpNotificationChannel("MyPushChannel");
CurrentChannel.Open();
CurrentChannel.BindToShellToast();
}
CurrentChannel.ChannelUriUpdated +=
new EventHandler<NotificationChannelUriEventArgs>(async (o, args) =>
{
// Register for notifications using the new channel
await MobileService.GetPush()
.RegisterNativeAsync(CurrentChannel.ChannelUri.ToString());
});
CurrentChannel.ShellToastNotificationReceived +=
new EventHandler<NotificationEventArgs(async (o, args) =>
{
RootFrame.Navigate(new Uri("/ItemPage.xaml"), args.Collection['1']);
});
}
I haven't tested any of this code, but it should be good enough to point you in the right directions. Basically,
Send the info you need to react in the Push Notification
Listen for event on your Client
Navigate to the frame you want to be on
Be sure to checkout this tutorial on Navigation: https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh771188.aspx

Resources