I'm handling branch io on Android now.
It's weird. If I close my app first and click the link, the link leads me to my app and opens the page which is supposed to be shown. But If I open my app and click the home button, and click the link, the link leads me to ap.. but the page is not shown. I just could see the main page without routing by branch io.
here this is my code.
#Override
protected void onStart() {
super.onStart();
branchIO();
}
private void branchIO() {
Branch branch= Branch.getInstance();
branch.initSession(new Branch.BranchReferralInitListener(){
#Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error == null) {
try{
Log.d("log", referringParams.toString());
//...my routing logic...
}catch(Exception e){
Log.e("log", "branch io error",e);
}
} else {
Log.i("log", error.getMessage());
}
}
}, this.getIntent().getData(), this);
BranchIO.branchUniversalObject.generateShortUrl(this, BranchIO.linkProperties, new Branch.BranchLinkCreateListener() {
#Override
public void onLinkCreate(String url, BranchError error) {
if (error == null) {
}
}
});
}
If I close my app first, the log is this
D/log: {"$og_title":"₩230000", "~creation_source":5, "$og_description":"blah blah", "+click_timestamp":1512100123,........"}
but If I open my app first and put it in the background, the log is this
D/log: {"+clicked_branch_link":false,"+is_first_session":false}
I read many StackOverflow and GitHub pages but couldn't find the solution.
Thanks for reading!
EDIT
I forgot to use this.setIntent(intent) in onNewIntent.
so after adding this, It worked well.
#Override
public void onNewIntent(Intent intent) {
this.setIntent(intent);
}
Thanks!
Aaron from Branch.io here.
There might be a few reasons you are seeing this error. Here are a few:
You aren't initializing Branch and handling deep linking in your
Main/Splash activity.
Your Main/Splash activity does not have the
launchMode set to singleTask
You aren't overriding onNewIntent()
in your Main/Splash activity
If you are using a
CustomApplicationClass, make sure you are initializing Branch with
Branch.getAutoInstance(this);
You can find an example Main/Splash activity here.
You can also check out our testbed application which is a complete working example of the Branch Android SDK here
Related
Our android app is a chat app. Users can paste a branch link in a chat message. When another user taps on it, we want to retrieve the link parameters to take the user to another screen.
Unfortunately, we are unable to retrieve the link parameters when we tap on such link inside the app (note that we are not using a webview), we are getting the error "Warning. Session initialisation already happened.
To force a new session, set intent extra, branch_force_new_session, to true in the onInitFinished(#Nullable JSONObject referringParams, #Nullable BranchError error) method.
How can we solve this? It's not obvious to me how I could pass a new intent param in that use case.
Notes:
Our launcher activity is singleTask
We are on branch.io sdk 4.3.2
onNewIntent() does not seem to be called (in the code below), maybe that is the root cause for our issue.
sample code:
private Branch.BranchReferralInitListener branchReferralInitListener =
new Branch.BranchReferralInitListener() {
#Override
public void onInitFinished(#Nullable JSONObject referringParams, #Nullable BranchError error) {
...
}
#Override
protected void onStart() {
super.onStart();
Branch.getInstance().initSession(branchReferralInitListener, getIntent() != null ?
getIntent().getData() : null, this);
}
#Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
this.setIntent(intent);
// activity will skip onStart, handle this case with reInitSession
Branch.getInstance().reInitSession(this, branchReferralInitListener);
}
This is a known issue with the Android SDK v4.3.2 and we are working on a resolution.
Would suggest you to try the following in the meanwhile:
When the user tries to open an app that is running in the background, we get an error for set branch_force_new_session to true.
Branch SDK gets initialised on onStart for the Launcher Activity and when the app comes foreground from the background, its on onResume.
In this scenario, we could need to re-initialise the SDK here.
Would request you to implement the below snippet as per Branch docs (https://docs.branch.io/apps/android/#initialize-branch)
// activity will skip onStart, handle this case with reInitSession
Branch.getInstance().reInitSession(this, branchReferralInitListener);
Alternatively, would suggest you to install Branch SDK v4.3.1.
Initialized, you branch IO in application class so that it will initialize once and will not be require again
// Branch logging for debugging
Branch.enableLogging();
//Disable Device ID #2966
Branch.disableDeviceIDFetch(true);
// Initialize the Branch object
BranchIOManager.setupBranchInstance(this);
// It tells the Branch initialization to wait for the Google Play Referrer before proceeding.
Branch.enablePlayStoreReferrer(1000L);
Then inside initSession() branch method use. Pass them as JSON Object to method where you can retrieve the value based on key names.
if (branch != null && uri != null) {
branch.initSession(new Branch.BranchUniversalReferralInitListener() {
#Override
public void onInitFinished(BranchUniversalObject branchUniversalObject, LinkProperties linkProperties, BranchError error) {
// Log.d("onInitFinished", error + "");
if (error == null && branchUniversalObject != null) {
JSONObject jBranch = branchUniversalObject.getContentMetadata().convertToJson();
if (!branchJSONString.equals(jBranch.toString())) {
//This check is applied as if we launch another mLandingScreenPhoneActivity from Branch link then app will become in loop
branchJSONString = jBranch.toString();
loadScreenFromBranchIODynamicLink(jBranch, 0);
}
}
if (error != null) {
// //Toast.makeText(LandingScreenPhoneActivity.this, error + "", Toast.LENGTH_SHORT).show();
}
}
}, uri, this);
}
Here you can get screen values
String screenName = referringParams.optString("screen_key");
//Screen in app where needs to navigate
int screenIndex = referringParams.optInt("screen_index");
I have a pretty straight forward setting, setup
my intent filters for my main activity on the manifest
singleTask mode for all my activities (it just have two)
My app have two entry points: one the intent filter will call my MainActivity which start the branch session return the values on the referringParams and I go to the SecondActivity, everyone is happy
the another entry point is the launcher, when I click open the MainActivity do somethhing different because intent.data is empty and Go to SecondActivity, the problem is as follows, after the app is in the SecondActivity and the app goes background (e.g. touch home button) and then tap on some link the MainActivity is launched intent.data is not empty there's a valid url but when my callback is called I got referringParams empty {}
I dont know what is wrong with this. i have spend some hours without success
#Override
public void onStart() {
super.onStart();
Branch branch = Branch.getInstance();
branch.initSession(new Branch.BranchReferralInitListener(){
#Override
public void onInitFinished(JSONObject referringParams, BranchError error) {
if (error == null) {
// here referringParams is a empty {} object
} else {
Log.i("MyApp", error.getMessage());
}
}
}, this.getIntent().getData(), this);
}
#Override
public void onNewIntent(Intent intent) {
this.setIntent(intent);
}
I am not sure what processing you are doing in your Main Activity. The use case you mentioned, should return the Branch link parameters correctly,
If you have the intent filters and the launchMode of the MainActivity, correctly defined
You are overriding the onNewIntent() method in your MainActivity (which I can see from the code snippet you shared)
I created a sample app, which is uploaded here. If you follow the test case you mentioned with this app(i.e. App is backgrounded with the SecondActivity), clicking on a Branch link returns the link parameters correctly.
I'm successful in creating a deeplink and posting it to facebook with all the relevant metadata attached:
TextView.OnClickListener inviteClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
BranchUniversalObject branchUniversalObject = new BranchUniversalObject()
// The identifier is what Branch will use to de-dupe the content across many different Universal Objects
.setCanonicalIdentifier("item/12345")
// This is where you define the open graph structure and how the object will appear on Facebook or in a deepview
.setTitle("Suits")
.setContentDescription("Great suits here")
.setContentImageUrl("http://steezo.com/wp-content/uploads/2012/12/man-in-suit.jpg")
// You use this to specify whether this content can be discovered publicly - default is public
.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC)
// Here is where you can add custom keys/values to the deep link data
.addContentMetadata("picurl", "http://steezo.com/wp-content/uploads/2012/12/man-in-suit.jpg");
LinkProperties linkProperties = new LinkProperties()
.setChannel("facebook")
.setFeature("sharing")
.addControlParameter("$desktop_url", "http://www.yahoo.com")
.addControlParameter("$ios_url", "http://www.microsoft.com");
ShareSheetStyle shareSheetStyle = new ShareSheetStyle(PlaceDetailsActivity.this, "Check this out!", "This stuff is awesome: ")
.setMoreOptionStyle(getResources().getDrawable(android.R.drawable.ic_menu_search), "Show more")
.addPreferredSharingOption(SharingHelper.SHARE_WITH.FACEBOOK)
.addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL);
branchUniversalObject.showShareSheet(PlaceDetailsActivity.this,
linkProperties,
shareSheetStyle,
new Branch.BranchLinkShareListener() {
#Override
public void onShareLinkDialogLaunched() {
}
#Override
public void onShareLinkDialogDismissed() {
}
#Override
public void onLinkShareResponse(String sharedLink, String sharedChannel, BranchError error) {
Log.e("LinkShared", "success");
}
#Override
public void onChannelSelected(String channelName) {
}
});
branchUniversalObject.generateShortUrl(PlaceDetailsActivity.this, linkProperties, new Branch.BranchLinkCreateListener() {
#Override
public void onLinkCreate(String url, BranchError error) {
if (error == null) {
Log.i("MyApp", "got my Branch link to share: " + url);
}
}
});
}
};
What I'm not successful at doing is to ensure that when the link is clicked, it goes to the correct activity within my app. I followed the guide closely but at points I found the guide to be a bit vague - https://dev.branch.io/references/android_sdk/#branch-universal-object-for-deep-links-content-analytics-and-indexing.
In the activity that I want to call, I put this in the manifest:
<activity
android:name=".SuitActivity"
android:label=""
android:windowSoftInputMode="adjustResize">
<meta-data android:name="io.branch.sdk.auto_link_keys_6" android:value="picurl" />
</activity>
Inside the SuitActivity class, I put in the following:
#Override
protected void onResume() {
super.onResume();
if (Branch.isAutoDeepLinkLaunch(this)) {
try {
action.setPicurl(Branch.getInstance().getLatestReferringParams().getString("picurl"));
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Log.e("nondeeplink","Launched by normal application flow");
}
}
That appeared to be all that needs to be done to click on a link in Facebook and open my SuitActivity instead of my MainActivity but it doesn't seem to work. When I click on a branch link, it opens MainActivity.
When I create the link on Branch, this is what is returned in the logs:
2-16 19:44:38.019 24086-24086/com.example I/MyApp: got my Branch link to share: https://bnc.lt/cByh/7d3u8enomp
12-16 19:44:38.021 24086-24129/com.example I/BranchSDK: posting to https://api.branch.io/v1/url
12-16 19:44:38.021 24086-24129/com.example I/BranchSDK: Post value = {
"identity_id": "20569XXX",
"device_fingerprint_id": "20519XXX",
"session_id": "2057XXX",
"tags": [],
"alias": "",
"channel": "Add to Facebook",
"feature": "sharing",
"stage": "",
"data": "{\"$og_title\":\"Suits\",\"$canonical_identifier\":\"item\\\/12345\",\"$keywords\":[],\"$og_description\":\"Great suits here\",\"$og_image_url\":\"http:\\\/\\\/steezo.com\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/man-in-suit.jpg\",\"$content_type\":\"\",\"$exp_date\":\"0\",\"picurl\":\"http:\\\/\\\/steezo.com\\\/wp-content\\\/uploads\\\/2012\\\/12\\\/man-in-suit.jpg\",\"$desktop_url\":\"http:\\\/\\\/www.yahoo.com\",\"$ios_url\":\"http:\\\/\\\/www.microsoft.com\",\"source\":\"android\"}",
"sdk": "android1.10.1",
"retryNumber": 0,
"branch_key": "key_test_XXX"
}
EDIT:
I have even added a GitHub sample now for you to test this: https://github.com/Winghin2517/BranchIOTestDeepLink
It includes two activities:
MainActivity with a FAB - it is the standard template for a new app created through Android Studios. If you click on the FAB, Branch.io will launch and ask you to add to facebook, copy link etc.
SecondActivity - once you have shared it on facebook and click on facebook on the link, the SecondActivity should start. Currently, when you click on the link on facebook or everywhere you have shared it, the link still opens MainActivity.
For this sample to work, please also replace your branch.IO key with your key from your profile in the manifest as currently, they are just XXX's:
<meta-data android:name="io.branch.sdk.BranchKey" android:value="key_live_XXX" />
<meta-data android:name="io.branch.sdk.BranchKey.test" android:value="key_test_XXX" />
Thanks!
The Github repo is now a working example of android with Branch.io after several days liaising back and forth with branch.io I finally got it to work:
https://github.com/Winghin2517/BranchIOTestDeepLink
The app will open the 'SecondActivity', and not the 'MainActivity', if you click on the link in facebook or wherever you decided to send the link to. If you click back from the 'SecondActivity', it will close the app as the onActivityResult method will be called in the 'MainActivity' with the correct activity code and the finish() method is called in 'MainActivity' to close the app.
I am trying to implement a referral code system, and I am using Branch.io Metrics library. The problem I am facing is that the documentation is not good (doesn't work) and I am unable to generate a code
Documentation:
https://github.com/BranchMetrics/Branch-Android-SDK#register-an-activity-for-direct-deep-linking-optional-but-recommended
Here are the steps I have taken including adding the library.
1) Grabbed the jar, added to my libs folder and added the following to my depenencies
compile files('libs/branch-1.5.9.jar')
2) In my application class that extends Application I added the following
if (DEBUG) {
Branch.getAutoTestInstance(this);
} else {
Branch.getAutoInstance(this);
}
3) In my AndroidManifest.xml I added the following
<meta-data android:name="io.branch.sdk.BranchKey" android:value="#string/bnc_app_key" />
4) In the Activity that I am testing everything, I added in the onStart() method the following
#Override
protected void onStart() {
// note that branch is a global variable (Branch branch;)
if (DEBUG) {
branch = Branch.getTestInstance(this.getApplicationContext());
} else {
branch = Branch.getInstance(this.getApplicationContext());
}
branch.initSession(new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
if (branchError == null) {}
}, this.getIntent().getData(), this;
}
From the above, I believe I have successfully created a branch.io session and a listener that will allow me to retrieve data if branchError is null (there are no conflicts)
While still inside onStart() I now try to generate a referral code. So the whole onStart() looks as follows:
#Override
protected void onStart() {
// note that branch is a global variable (Branch branch;)
if (DEBUG) {
branch = Branch.getTestInstance(this.getApplicationContext());
} else {
branch = Branch.getInstance(this.getApplicationContext());
}
branch.initSession(new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
if (branchError == null) {}
}, this.getIntent().getData(), this;
}
branch.getReferralCode(5, new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
try {
String code = jsonObject.getString("referral_code");
Log.d(TAG, "code: " + code);
} catch (JSONException e) {
Log.e(TAG, "JSONException :: " + e);
e.printStackTrace();
}
}
});
}
5) I added onNewIntent override method
#Override
protected void onNewIntent(Intent intent) {
this.setIntent(intent);
}
My app does not reach inside of the onInitFinished listener, so I am unable to retrieve any code(s). Any suggestions on what I have missed is appreciated, and hopefully this thread will fill the holes that the documentation lacks.
I'm going to assume that the following lines of code are properly closed and aren't throwing syntax errors:
branch.initSession(new BranchReferralInitListener() {
#Override
public void onInitFinished(JSONObject jsonObject, BranchError branchError) {
if (branchError == null) {}
}, this.getIntent().getData(), this); // parenthesis wasnt here
First, if you are extending the Application class, you need to initialize branch inside the onCreate() callback of your Application class:
public void onCreate() {
super.onCreate();
Branch.getInstance(this);
}
As per the Branch sample code found here, you actually need to call:
Branch.getInstance();
Instead of:
Branch.getInstance(getApplicationContext());
Inside your activities onCreate callback. Once that is taken care of, the Branch SDK will properly create.
I am attempting to write a RemotePlaybackClient sample app, in part because the one published by Google crashes aapt.
I can get RemotePlaybackClient to support play(), and it plays back a video on a Chromecast.
However, when I call stop(), to stop playback of the video, while the Chromecast does stop playback (showing a black screen with a cast icon centered), the SessionActionCallback that I pass into the stop() call does not get called with onResult():
private void stop() {
logToTranscript(getActivity().getString(R.string.stop_requested));
SessionActionCallback stopCB=new SessionActionCallback() {
#Override
public void onResult(Bundle data, String sessionId,
MediaSessionStatus sessionStatus) {
logToTranscript(getActivity().getString(R.string.stopped));
isPlaying=false;
isPaused=false;
getActivity().supportInvalidateOptionsMenu();
endSession();
}
};
client.stop(null, stopCB);
}
The same thing happens if I try pause() -- the SessionActionCallback passed to pause() is not invoked.
The sample code published by Google shows that these callbacks should be invoked, but, again, I can't get that to compile successfully.
Does anyone know under what circumstances the SessionActionCallback would not work, while the ItemActionCallback used with play() would work?
UPDATE
I have filed issue 66996 and issue 67032, the latter of which is specifically the problem I am seeing here, as I run into this same problem with the official sample app.
I beleive all Answer reside on how you make connection.
Because in google code ,code says that client which you had made shold not leave session and should not be null.
if (!mClient.hasSession()) {
// ignore if no session
return;
}
/*********Rest of the code would be unreachable***********/
#Override
public void pause() {
if (!mClient.hasSession()) {
// ignore if no session
return;
}
if (DEBUG) {
Log.d(TAG, "pause");
}
mClient.pause(null, new SessionActionCallback() {
#Override
public void onResult(Bundle data, String sessionId, MediaSessionStatus sessionStatus) {
logStatus("pause: succeeded", sessionId, sessionStatus, null, null);
if (mCallback != null) {
mCallback.onPlaylistChanged();
}
}
#Override
public void onError(String error, int code, Bundle data) {
logError("pause: failed", error, code);
}
});
}