I'm trying to get deferred deep links working on Android. I added a test device in the dashboard & reset the device data and made sure the app is uninstalled. When I click a branch.io link, it takes me to the play store as expected. I then launch the app from Android Studio onto the phone, then the logs say that Branch SDK sent a request to https://api2.branch.io/v1/install, but the problem is the response doesn't contain the original link, query params, or key value pairs I set in the dashboard. This is the JSONObject I'm receiving in onInitFinished:
{"+match_guaranteed":true,"link_click_id":"976953359423305632","+clicked_branch_link":true,"+click_timestamp":1634196720,"+is_first_session":true,"utm_source":"test-referrer"}
Where is all the other information? This doesn't include the original link, the key-value pairs, tags, etc.
For a comparison, this is what I receive in the iOS app:
["$ios_passive_deepview": "branch_passive_default", "source": "test-referrer", "+is_first_session": 1, "~channel": test-referrer, "$matching_ttl_s": 7200, "~id": 976763609660742721, "~creation_source": 1, "$one_time_use": 0, "~marketing": 1, "~referring_link": "https://myapp.test-app.link/test-referrer", "~feature": "test", "+click_timestamp": 1634249299, "+match_guaranteed": 0, "$og_description": "My app description", "$og_title": "MyApp", "+clicked_branch_link": 1, "$marketing_title": "Test Referral Link", "~tags": ["test-referrer"], "~campaign": "test"]
If I rotate the phone to recreate the Activity or reopen the app a single time, it then sends a request to https://api2.branch.io/v1/open and returns all the info I expected initially. How do I get the information after installing the app?
I'm currently testing with myapp.test-app.link, and I call Branch.enableTestMode() before Branch.getAutoInstance(this) in my custom Application class's onCreate(). I also tried with a live link and got the same result.
These are the libraries I'm using in build.grade:
implementation 'io.branch.sdk.android:library:5.0.13'
implementation 'com.google.firebase:firebase-appindexing:20.0.0'
implementation 'com.google.android.gms:play-services-ads-identifier:17.1.0'
implementation 'androidx.browser:browser:1.3.0'
I've also set up app links and the uri scheme in the dashboard as well as in the app. Using getFirstReferringParams() and getLatestReferringParams() on the first session after installing doesn't help either.
UPDATE:
Repeating the exact same testing process I described above, now the JSONObject that gets passed into onInitFinished has even less information and is claiming that I'm not clicking a branch link:
{"+clicked_branch_link":false,"+is_first_session":true}
And getFirstReferringParams() returns an empty json object.
I'm about to start looking for an alternative at this rate.
I fixed this issue by adding intent.putExtra("branch_force_new_session", true); right after this.activity.setIntent(intent); when initialising the intent. Something like this:
...
this.activity.setIntent(intent);
intent.putExtra("branch_force_new_session", true);
Branch
.sessionBuilder(this.activity)
.withCallback(branchReferralInitListener)
.reInit();
...
Look here for the branch_force_new_session reference.
The other reason for the missing data is the non-existent link alias, but it looks like it is not the case as soon as you tried with the same link in iOS.
Related
I created 2 policies in my enterprise.
I would like to switch one device to the other policy without re-enroling it.
I tried to use android management enterprises devices.patch with following JSON
{ "policyName": "policy2" }
this link
When i execute this command i always get follwoing error Message:
{
"error": {
"code": 400,
"message": "Illegal state transition from ACTIVE to DEVICE_STATE_UNSPECIFIED",
"status": "INVALID_ARGUMENT"
}
}
Does anybody know how to change policy for a device without wiping it?
It is indeed possible to change the policy of a device without re-enrolling it, and you're not far from the solution.
You get this error because you implicitly attempt to change other fields of the Device resource (in particular the state field) by not setting them in the resource that you send in devices.patch.
You have two options:
Set the updateMask in devices.patch to "policyName", to tell the API that you only want to change the policyName field.
Call devices.get to get the current Device resource, and then send back the entire resource with only the policyName field changed in to devices.patch.
Using updateMask is preferable because it does an atomic read-modify-write.
As Fred mentioned, updateMask is the preferred way to go. Here's an example of how to use the updateMask approach in the Google colab
swap_result = androidmanagement.enterprises().devices().patch(
name='enterprises/ENTERPRISE_NAME/devices/DEVICE_ID', updateMask='policyName', body={ "policyName": "enterprises/ENTERPRISE_NAME/policies/NEW_POLICY_NAME"}).execute()
i foudn a solution for my problem:
{ "policyName": "policy2" , "state":"active"}
If you try this from management api test site then add updateMask as "policyName"
I am using the new GoogleConnect thing and set the scope like
Login gc = GoogleConnect.getInstance();
gc.setScope("https://www.googleapis.com/auth/plus.profile.emails.read https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file");
...
gc.doLogin();
However, when the access token is generated and checked in
https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=(accesstoken)
, it shows
"scope": "https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.profile"
Is it related to any recent updates or new build hint?
I am totally lost here. It is an Android build.
Thanks.
Edited to add gc.doLogin() code, to clarify that I am NOT trying to set the scope after the access token is generated.
Same problem here, setScope only works on the simulator
"scope": "https://www.googleapis.com/auth/plus.me https://www.googleapis.com/auth/userinfo.profile",
My scopes (for reference):
google.auth.scopes=https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.me email profile
I'm working on Ionic mobile app development.
My requirement is to create client side logger to track issues in app. I used the methods mentioned in https://github.com/pbakondy/filelogger, and I could able to create the log file in both Android and iOS.
For the first time when I open the app, it creates the log file in cordova.file.dataDirectory, when I close and reopen the app in i*OS, I'm trying to read the content of the file which was created using the below
$fileLogger.getLogfile().then(function (loggerContent) {
var temp =loggerContent;
});
But the application says
{
"applicationDirectory":null,
"applicationStorageDirectory":null,
"dataDirectory":null,
"cacheDirectory":null,
"externalApplicationStorageDirectory":null,
"externalDataDirectory":null,
"externalCacheDirectory":null,
"externalRootDirectory":null,
"tempDirectory":null,
"syncedDataDirectory":null,
"documentsDirectory":null,
"sharedDirectory":null
}
So I couldn't able to find the file where i saved my logs.
Please help me resolve this issue or if you could recommend me a different method to get around this issue, that would be great!
Thanks for the answers
There is a check list here and should solve your problem :
1-Be sure that the cordova-file-plugin is installed and works in your test environment.
2-Be sure that the cordova.js file is refrenced by your html and before your code usage.
3-Be sure to call your codes after device_ready state :
check this
4-Call your function after a short delay (use setTimeOut in Javascirpt)
Ali's item 4 is very important:
I had a similiar problem on different platforms: cordova.file.dataDirectory was null.
I tracked cordova.file.dataDirectory over the lifecycle and it was first accessed by my Ionic 2 code BEFORE the device ready event was fired.
My "mistake": I wanted to load data during the constructor(!) of a service. Seems too early.
I am trying to integrate Firebase RemoteConfig and Analytics with my Android application. Remote configuration part is working but Analytics part is not working. Here is my build.gradle
// Firebase configuration
compile group:'com.google.firebase', name:'firebase-core', version: '9.4.0'
compile group:'com.google.firebase', name:'firebase-config', version: '9.4.0'
// Firebase analytics
compile 'com.google.android.gms:play-services-analytics:9.4.0'
Here is my Activity code.
FirebaseAnalytics firebaseAnalytics = FirebaseAnalytics.getInstance(this);
firebaseAnalytics.setUserId("5107611364");
firebaseAnalytics.setUserProperty("custom_user_property", "custom_user_proerty_value");
Bundle bundle = new Bundle();
bundle.putString(FirebaseAnalytics.Param.ITEM_ID, "SomeID");
bundle.putString(FirebaseAnalytics.Param.ITEM_NAME, "SomeIDName");
bundle.putString(FirebaseAnalytics.Param.CONTENT_TYPE, "IdType");
firebaseAnalytics.logEvent(FirebaseAnalytics.Event.SELECT_CONTENT, bundle);
I am trying to publish customer property as well as the event but both of them are not working. I have enabled adb logging and I can see that custom event and property are published. These do not appear on the Firebase Analytics console even after 24hrs. I don't know what is wrong.
#Rakesh - you are looking in the wrong location. You are supplying customID feilds, in your example you are supplying CONTENT_TYPE : IdType. You don't need a minimum of 10 users to see the data...if you only have 1 user that data will appear within 24 hours of that user using your app.
I will say this, initially finding your own custom IDs is not very straight forward...it took me a while to find it too.
The place to find that custom reported info is: Anaylytics - Events - once on this page, click on the actual CONTENT_TYPE you are wishing to track, in your example above, it would be idType
Then on the Content graph you will see your customIDs (ie: someID)...click on someID. In my case (and in my screenshots) my equivelant someIDs are "field, button & select"
and then you will see all the data related to the values (someIDName) you passed into someID.
Now, if idType is not appearing for you then that may because Firebase isn't allowing you to create your own CONTENT_TYPE, I am not certain if you can do that as I have not tried...and in that case you would need to use a predefined CONTENT_TYPE. I am not using a custom idType, I am using CONTENT_TYPE : select_content.
Latest Update Below at Update #5
I'm trying to implement AppLinks for BOTH my iOS AND Android apps : http://applinks.org
I've done the following:
setup a custom url scheme for my app: inacho://
Setup in my App Delegate: - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
Add meta tags to my website at http://www.nachorater.com :
<meta property="al:ios:app_store_id" content="581815579"/>
<meta property="al:ios:app_name" content="iNacho" />
<meta property="al:ios:url" content="inacho://default" />
I've verified that the url scheme works great by typing in a link like inacho://default into Notes and clicking the link it creates. Wa-la! It opens my app.
But when I try clicking on a link to www.nachorater.com from Facebook or Quip, neither app automatically seems to take any notice that the site has these app links setup and it just loads the website in their browser(s) instead of trying to open my app.
Has anyone got this working?
Update:
I had an issue with some meta tags not being in the < head > portion of my templates and I fixed it.
Now the link: http://www.nachorater.com from the iOS Facebook app adds a nice little popup that lets you open the url in the iNacho app like so:
But my links to my dynamic reviews do not seem to be working, yet the Debug app that Ming pointed out shows that the meta tags look correct for them.
For example, http://www.nachorater.com/getReview?reviewID=6396169718595584
meta tags when debugging with https://developers.facebook.com/tools/debug/og/object?q=http%3A%2F%2Fwww.nachorater.com%2FgetReview%3FreviewID%3D6396169718595584 :
Update #2:
I posted a new nacho review link to my iNacho Facebook timeline and then tried to click on it from the Facebook Mobile app.
It started to load the page and popped up the handy indicator that lets you open the app in iNacho but then once the page loaded, the indicator went away (before I could click it).
Update #3:
From the Facebook app, I can now trigger an inacho URL for my reviews BUT it's ONLY if I click the little popup to open in iNacho before it disappears. If I let the page completely load in Facebook's built-in web view, the little popup disappears still.
Is this a problem with Applinks? Or a problem with the Facebook app? Or by design and why?
Update #4:
I may know what the problem is. The review page in turn loads up a dynamic image for the nacho review. So by loading the page, it has an img src tag that points to a dynamic url that loads the image. Is this being mistaken for a 'redirect' action of some sort?
Example of img tag (rendered): <img width="300" src="/getReviewImage?imageID=6125868501958656"></img>
Note: There are a bunch of other scripts/ajax that gets loaded dynamically too though (Facebook and twitter widgets and the like).
Is this a bug in AppLinks or the Facebook Mobile app? Shouldn't it not care about background loading objects like ajax and dynamic images?
Update #5
7/15/14 - This is still happening with latest Facebook app. When I click a link from my iNacho Facebook page to my iNacho website, it pops up the option to open it in the app for a split second before the page finishes loading. Then it hides it.
As for the twitter app, it does not even give me the popup for a split second. It doesn't seem to recognize the link is appslink enabled at all.
Quip on the other hand, I pasted a nacho link in and the first time I clicked on it, it went to its built-in safari with no option to open in my app. BUT the second time I clicked it, it directly opened my app instead.
Summary: So far, it seems like maybe some apps are implementing the AppLinks Navigation portion incorrectly or something. Quip seems to work but even Facebook's own app seems like it's not working.
I was having the same problem with AppLinks and decided to just forego them altogether and just use facebook's app link host: https://developers.facebook.com/docs/applinks/hosting-api
My app is really mobile only, and I misunderstood how AppLinks worked at first. I thought I could just put the al_ios_* meta tags on a single, universal web page but this is wrong. There would need to be a separate page for every piece of content on my site, and each one of those pages needs to have its own AppLinks meta tags to send a URL for that specific content back to my app.
When I was doing it wrong, when I tapped on my OpenGraph story in facebook, it would open my site in the web browser and there was an action icon in the bottom toolbar that I could tap and have the option to open my app. Or I would have to precision-tap the name of my app in the OpenGraph story. Either of those fast-switch to my app, but the URL would not be specific to the content I want my app to navigate to. Also, both of those options suck -- I just want to tap anywhere on the story and go straight to my app, which is why we're all here.
The solution
I am going to use an OpenGraph story with the share dialog as an example.
First, you need to create a hosted app link on your server, not in the app. Before creating your OpenGraph story or whatever is being shared, make a call to your server to accomplish 2 things:
1.) Make an API call to create a new facebook app link, which will give you back an ID
2.) Use that ID to make a 2nd API call to get the URL to your hosted app link
This has to be done on the server because these API calls require an app access token, not a user access token. This token has app level permissions, not user level permissions. You cannot and should not store your facebook app secret anywhere in your mobile application because someone could decompile your app and make changes to your facebook app. No good. Use your server because it can safely know your app secret.
My server side is in PHP so here is an example of how to accomplish this. Dealing with the API wasn't a particularly pleasant experience, so I'll share in hopes that it helps someone else with formatting the requests:
# create a new facebook app link using cURL
$metadata = <what to handle in AppDelegate application:openURL:sourceApplication:annotation>;
$url = "https://graph.facebook.com/v2.1/app/app_link_hosts";
$ch = curl_init($url);
# create form post data
$deepLinkURL = "<myApp>://" . $metadata;
$iosArray = json_encode(array(array("url" => $deepLinkURL,
"app_store_id" => <appStoreId (number)>,
"app_name" => "<myAppName>")
)
);
$webFallbackArray = json_encode(array("should_fallback" => false));
$formQuery = http_build_query(array("access_token" => "<appId>|<appSecret>",
"name" => $metadata,
"ios" => $iosArray,
"web" => $webFallbackArray)
);
# options
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $formQuery);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
# get response
$responseJson = curl_exec($ch);
curl_close($ch);
# decode response from facebook
$jsonResponse = json_decode($responseJson, true);
$appLinkId = "";
# get appLinkId
foreach ($jsonResponse as $key => $val) {
# get status
if($key == "id") {
$appLinkId = $val;
}
}
# if response is good, need to request canonical URL from appLinkId
$errorMessage = "";
$canonicalUrl = "";
if(!empty($appLinkId)) {
# create another instance of cURL to get the appLink object from facebook using the ID generated by the previous post request
$getAppLinkUrl = "https://graph.facebook.com/" . $appLinkId;
$ch2 = curl_init();
# cURL options
$queryString = http_build_query(array("access_token" => "<appId>|<appSecret>",
"fields" => "canonical_url",
"pretty" => true)
);
curl_setopt($ch2, CURLOPT_URL, $getAppLinkUrl . "?" . $queryString);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
# get response
$urlResponseJson = curl_exec($ch2);
curl_close($ch2);
# decode response from facebook
$urlJsonResponse = json_decode($urlResponseJson, true);
# parse response to get canonical URL
foreach ($urlJsonResponse as $key => $val) {
# get canonical URL
if($key == "canonical_url") {
$canonicalUrl = $val;
}
}
# check for result
if(empty($canonicalUrl)) {
$errorMessage = "Unable to retreive URL.";
}
} else {
$errorMessage = "Unable to publish appLink.";
}
# encode response back to your app
if(empty($errorMessage)) {
$response = json_encode(array("result" => "success",
"canonical_url" => $canonicalUrl));
} else {
$response = json_encode(array("result" => "failed",
"errorMessage" => $errorMessage));
}
#send response back to your app
Back in your app, once you confirm a good response, put the canonical URL you get back as the url parameter in [FBGraphObject openGraphObjectForPostWithType: below. Now when you click on your story in the facebook app, it will go straight to your app. No web nonsense.
// Create an action
id<FBOpenGraphAction> action = (id<FBOpenGraphAction>)[FBGraphObject graphObject];
// Create an object
id<FBGraphObject> object;
// set shareDialog parameters
FBOpenGraphActionParams *params = [[FBOpenGraphActionParams alloc] init];
params.action = action;
params.actionType = #"<myApp>:<myAction>";
params.previewPropertyName = #"<key>";
object = [FBGraphObject openGraphObjectForPostWithType:#"<myApp>:<myObject>"
title:<title>
image:<urlToPic>
url:<fb.me/xyz canonical URL>
description:<someDescription>];
[action setObject:object forKey:#"<key>"];
etc...
When I was working on my app, Sweep, I put a pay/share wall after a certain amount of time spent in the app. I faced the same problem where AppLinks really sucked at actually linking off of Facebook, despite the promise. Based on this problem, I built a service called branch.io that hosts the links for me, plus automatically inserts the correct AppLinks metatags for Android/iOS. The links actually work as expected, as crazy as that is. It uses a combination of client side JS with the AppLinks to make them properly redirect in every webview and native browser
Here's a high level guide to creating the share links on iOS:
To get started, you just need to configure the location of your app in either store on the dashboard at dashboard.branch.io. Once it's all setup, you get your Branch app key.
pod "Branch" or you can clone the open source repo here:
https://github.com/BranchMetrics/Branch-iOS-SDK
Add the Branch key to your plist file as a String with the key 'branch_key'
Add the following code to your AppDelegate in the appropriate methods
In the didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// your other init code
Branch *branch = [Branch getInstance];
[branch initSessionWithLaunchOptions:launchOptions andRegisterDeepLinkHandler:^(NSDictionary *params, NSError *error) { // previously initUserSessionWithCallback:withLaunchOptions:
if (!error) {
// params are the deep linked params associated with the link that the user clicked before showing up
// params will be empty if no data found
// here is the data from the example below if a new user clicked on Joe's link and installed the app
NSString *name = [params objectForKey:#"user"]; // returns Joe
NSString *profileUrl = [params objectForKey:#"profile_pic"]; // returns https://s3-us-west-1.amazonaws.com/myapp/joes_pic.jpg
NSString *description = [params objectForKey:#"description"]; // returns Joe likes long walks on the beach...
// route to a profile page in the app for Joe
// show a customer welcome
}
}];
}
In the openUrl for handling URI calls:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
// pass the url to the handle deep link call
// if handleDeepLink returns YES, and you registered a callback in initSessionAndRegisterDeepLinkHandler, the callback will be called with the data associated with the deep link
if (![[Branch getInstance] handleDeepLink:url]) {
// do other deep link routing for the Facebook SDK, Pinterest SDK, etc
}
return YES;
}
Lastly, to create the hosted links, it's very simple. You just need to call getShortUrl to dynamically create one. You can put as many keys and values in the links as possible (to be retrieved in the initSession callback)
You can put this snippet anywhere you want to create a link:
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
[params setObject:#"Joe" forKey:#"user"];
[params setObject:#"url.to.picture/mypic.png" forKey:#"profile_pic"];
[params setObject:#"Joe likes long walks on the beach..." forKey:#"description"];
// Customize the display of the link
[params setObject:#"Joe's MyApp Referral" forKey:#"$og_title"];
[params setObject:#"url.to.picture/mypic.png" forKey:#"$og_image_url"];
[params setObject:#"Join Joe in MyApp - it's awesome" forKey:#"$og_description"];
// Customize the redirect performance
[params setObject:#"http://myapp.com/desktop_splash" forKey:#"$desktop_url"];
Branch *branch = [Branch getInstance];
[branch getShortURLWithParams:params andCallback:^(NSString *url, NSError *error) {
// show the link to the user or share it immediately
}];
Android is very similar in method calls and functionality and can be found on the site.
sorry if my answer is not exactly what you expect but just to share what we did on our websites and apps.
For instance, I know we had to add more tags to make it works with twitter cards and here is the list of the meta properties we have in our pages:
meta property="twitter:card" content=""
meta property="twitter:title" content=""
meta property="twitter:description" content=""
meta property="twitter:image:src" content=""
meta property="twitter:app:id:iphone" content=""
meta property="twitter:app:name:iphone" content="Marmiton"
meta property="twitter:app:url:iphone" content=""
meta property="twitter:app:id:googleplay" content=""
meta property="twitter:app:name:googleplay" content=""
meta property="twitter:app:url:googleplay" content=""
and the metha you also have:
meta property="al:iphone:app_store_id" content=""
meta property="al:iphone:app_name" content=""
meta property="al:iphone:url" content=""
meta property="al:android:package" content=""
meta property="al:android:app_name" content=""
meta property="al:android:url" content=""
we also have the facebook opengraph meta defined such as fb:app_id. I mention that because when you receive the deeplink in your app, you also have the facebook app id in the applinks link.
And from what we tested:
facebook does not open the deeplink directly on iOS whereas Android gives you the app choice. It sometimes shows up the blue popup at the bottom of the screen and sometimes you just have a link added in the actionsheet you have when you tap on the share button in the facebook (safari) webview (only at first load)-> this presentation of the link depends on how the content was shared on facebook.
twitter add a link to the app inside the card on iOS.
Don't know what I can add more.
Hope it helps a bit.