I'm using FB AppInvite with a deep link. When I press the "Open" from the invite I get the deep link correctly.
The problem is that once I do that, all subsequent activations of the app are activating the onDeferredAppLinkDataFetched() callback with the same deep-link. It doesn't matter if I launch the app from the launcher or from the overview screen.
Here is the code:
if (targetUrl != null) {
Log.d(TAG, "App Link Target URL: " + targetUrl.toString());
processReferral(targetUrl.toString());
} else {
AppLinkData.fetchDeferredAppLinkData(
activity,
new AppLinkData.CompletionHandler() {
#Override
public void onDeferredAppLinkDataFetched(AppLinkData appLinkData) {
String deeplink = appLinkData.getTargetUri().toString();
Log.w(TAG, "Deferred App Link Target URL: " + deeplink);
// This is happening too aggresively - every activation after one acceptance
processReferral(deeplink);
}
});
}
Will appreciate any clue :-)
Related
I'm trying to implement WeChat InApp payments in our app. But we are struggling to make it work.
I will try to sum it up real quick.
Given user is not logged in, WeChat login screen show up every time.
Given user is logged in, when clicked on pay button for a first time, WeChat order info screen shows up, but when clicked back, and clicked on pay button again (in our app), WeChat screen doesn’t show up.
We did implemented WXPayEntryActivity but neither onCreate, onNewIntent nor onResp are called. And yes, this activity is sending broadcast but neither toast nor log shows up.
I tried call registerApp on application started, I tried it just before creating payment req.
Did anybody come across this issue?
Can WeChat help me directly?
Want to see some code?
This is my payment class
public class WXInAppPayment {
public void startPayment(AppCompatActivity activity, PaymentDataResponse data) {
IWXAPI api = getApi(activity);
if (api.isWXAppInstalled()) {
api.sendReq(getPayRequest(data));
} else {
// Showing toast
}
}
public WXReceiver getReceiver() {
// returning BR for wechat payments
return new WXReceiver();
}
public IntentFilter getIntentFilter() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Constants.WE_CHAT_BR_ID);
return intentFilter;
}
private IWXAPI getApi(AppCompatActivity activity) {
final IWXAPI api = WXAPIFactory.createWXAPI(activity, null);
api.registerApp(Constants.WE_CHAT_APP_ID);
return api;
}
private PayReq getPayRequest(PaymentDataResponse data) {
PayReq request = new PayReq();
request.appId = dataFromAPI.appId;
request.partnerId = dataFromAPI.partnerId;
request.prepayId = dataFromAPI.prepayId;
request.packageValue = dataFromAPI.packageValue;
request.nonceStr = dataFromAPI.nonceStr;
request.timeStamp = dataFromAPI.timestimeStampamp;
request.sign = dataFromAPI.sign;
return request;
}
}
And this is WXPayEntryActivity. In manifest:
<activity android:name=".wxapi.WXPayEntryActivity"
android:label="#string/app_name"
android:exported="true"/>
And class:
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private final String TAG = getClass().getSimpleName();
private IWXAPI api;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, Constants.WE_CHAT_APP_ID);
api.handleIntent(getIntent(), this);
}
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
}
#Override
public void onReq(BaseReq baseReq) {
Log.e(TAG, "onReq: " + baseReq.transaction);
}
#Override
public void onResp(BaseResp baseResp) {
Log.e(TAG, "onResp: " + baseResp.errStr + " " + baseResp.errCode);
Intent intent = new Intent(Constants.WE_CHAT_BR_ID);
intent.putExtra("error_code", baseResp.errCode);
intent.putExtra("error_string", baseResp.errStr);
sendBroadcast(intent);
finish();
}
}
I went through same issue... Your code look fine.
lets cover the scenario:
This is normal ... if user is not logged in.. Wechat App will
redirect to login screen
"Only first time payment passed" happened due to wrong packageName. consider these checks:
You need to use ApplicationId not packageName
WhiteSpace
Debug buildType by default has suffix: .debug to applicatonId
Check AppSign which is MD5 of cert you sign with.. Be careful not to use the default one for debug buildType.
Try to reassign ApplicationId and AppSign it again.(that was our issue 😞) due to hidden WS not visible.
Contact Wechat team support.. they have logs to payment.
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.
Recently I tested 'deferred deeplink' function by using facebook SDK.
But there is one problem.
# I did it.
First, I have completed all of setting for apps by using the "App Ads Helper" function from developers.facebook.com.
https://developers.facebook.com/tools/app-ads-helper
Second, so I obtained the good result by using "DeepLink Test" provided by"App Ads Helper".
And I could see what i want (AppLinkData)
06-04 12:58:25.598 11903-11925/? I/DEBUG_FACEBOOK_SDK﹕ Bundle[{com.facebook.platform.APPLINK_NATIVE_CLASS=, target_url=myapp://myapp.co.kr?test=1111, com.facebook.platform.APPLINK_NATIVE_URL=myapp://myapp.co.kr?test=1111}]
Third, here is the code what I used.
protected void onCreate(){
....
FacebookSdk.sdkInitialize(getApplicationContext());
AppLinkData.fetchDeferredAppLinkData(getApplicationContext(),
BSTracker.getInstance().getFacebookIdMeta() ,
new AppLinkData.CompletionHandler() {
#Override
public void onDeferredAppLinkDataFetched(AppLinkData appLinkData) {
if (appLinkData != null) {
Bundle bundle = appLinkData.getArgumentBundle();
Log.i("DEBUG_FACEBOOK_SDK", bundle.toString());
} else {
Log.i("DEBUG_FACEBOOK_SDK", "AppLinkData is Null");
}
}
});
}
Finally. This is My App Setting
Ad Setting
It is My Ad setting.
i did input the DeepLink in "Get install of your App" Ad Product.
# Problem
When I created commercial ad at Facebook and released for the audience but I can't get Deferred DeepLink.
Please let me know, anything is wrong with it.
I'm trying to implement Facebook sharing in my game using Unity 3D + Facebook Unity SDK. But when I tried testing to post to my wall, this error shows up: "We are Sorry, this post is no longer available. It may have been removed." Can anybody help me? Thanks in advance.
BTW, here's my code:
using UnityEngine;
using System.Collections;
public class FacebookController : MonoBehaviour {
public bool isUsingFacebook = true; //Are we using Facebook SDK? This variable is only
//Feed parameters.
private string link = "market://details?id=com.LaserCookie.Queue"; //The link that will show the user the game's google play store address
private string linkName = "Queue"; //The link name
private string linkCaption = "Wow this game is great! 10/10 must play!"; // The caption of the link
private string linkDescription = "I achieved the score of " + PlayerController.instance.score.ToString() + "! Try to beat me if you can!"; //The description of the link
private string picture = "http://www.drycreekequestriancenter.com/testImage.jpeg"; //This is the image / game icon for the link. For now, it's shamelessly got from a random source. Thank you, random citizen...
void Awake()
{
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
//Init FB
private void Init()
{
if (!FB.IsInitialized)
{
FB.Init(OnInitComplete, OnHideUnity);
}
}
//Callback that will be called when the initialization is completed
private void OnInitComplete()
{
Debug.Log("FB.Init completed: Is user logged in? " + FB.IsLoggedIn);
//Check if we are logged in.
//If not, we will log in.
//If we are, post status.
if (!FB.IsLoggedIn)
{
LoginWithPublish();
}
else
{
PostImpl();
}
}
//Callback that will be called when the game is shown / not
private void OnHideUnity(bool isGameShown)
{
Debug.Log("Is game showing? " + isGameShown);
}
//Post to Facebook. This is the only exposed method because we only use this to post to Facebook.
//The initialization and login will be called when needed.
//It will first detect whether or not we have been initialized. And will init if we haven't.
//Then it will check whether or not we have been logged in with publish. And will log in if not.
public void PostToFacebook()
{
//Are we using facebook SDK?
if (isUsingFacebook)
{
if (!FB.IsInitialized) //Check for initialization
{
Init();
}
else if (!FB.IsLoggedIn) //Check for login
{
LoginWithPublish();
}
else //Post if we are already initia;ized and logged in
{
PostImpl();
}
}
}
//The true implementation of the posting
private void PostImpl()
{
FB.Feed("",link, linkName,linkCaption,linkDescription,picture);
}
//Login to Facebook with publish
private void LoginWithPublish()
{
// It is generally good behavior to split asking for read and publish
// permissions rather than ask for them all at once.
//
// In your own game, consider postponing this call until the moment
// you actually need it.
FB.Login("publish_actions", LoginCallback);
}
//Login callback
void LoginCallback(FBResult result)
{
if (result.Error != null)
{
Debug.Log( "Error Response:\n" + result.Error );
//TODO: Retry login if we have error? Or do we display a pop up?
}
else if (!FB.IsLoggedIn)
{
Debug.Log( "Login cancelled by Player" );
//TODO: Do we display a pop up?
}
else
{
Debug.Log( "Login was successful!" );
PostImpl();
}
}
}
You need to add Key Hash for FB application.
Go to My Apps, select you application, open Setting tab, add platform for android, and add you key hash.
check this link out
Setting a Release Key Hash
I've fixed the issue. It turns out it's because I used my still in development google store address as the link. I thought it would be automatically recognized regardless of my app is live or not. Thank you anyway. :)
I trying use Dungeons example in my app. In Android development guide it's written that I should confirm delivery product to user sending CONFIRM_NOTIFICATIONS to market, but I don't see it in example or am I wrong? Should I confirm download and my app should remember if content was successfully delivered?
Where is the best place to invoke downloading, in activity using AsyncTask, in ResponseHandler class or different?
This is something that I've been wondering about today too. From what I can see, in the Dungeons example, when BillingService#purchaseStateChanged is called, it automatically acknowledges all notifications after verifying the purchases.
See lines 506-509 in the example BillingService.java:
if (!notifyList.isEmpty()) {
String[] notifyIds = notifyList.toArray(new String[notifyList.size()]);
confirmNotifications(startId, notifyIds);
}
The solution would appear to be relocating this logic to a place you can manually call when you have completed delivery of your content.
I'm planning to remove that code and make the BillingService#confirmNotifications public so I can call it from my PurchaseObserver implementation when I've delivered my content.
I'll update with the result, but it seems to be a good starting point.
I hope Following Code helps u.
#Override
public void onPurchaseStateChange(PurchaseState purchaseState, String itemId,
int quantity, long purchaseTime, String developerPayload) {
if (Consts.DEBUG) {
Log.i(TAG, "onPurchaseStateChange() itemId: " + itemId + " " + purchaseState);
}
if (developerPayload == null) {
logProductActivity(itemId, purchaseState.toString());
} else {
logProductActivity(itemId, purchaseState + "\n\t" + developerPayload);
}
if (purchaseState == PurchaseState.PURCHASED) {
mOwnedItems.add(itemId);
Log.v("log_tag", "Item Purchased");
}
mCatalogAdapter.setOwnedItems(mOwnedItems);
mOwnedItemsCursor.requery();
}
In Log if you get "Item Purchased" it indicates that you have successfully download the Item.