· 6 years ago · Mar 26, 2020, 05:40 AM
1package io.branch;
2
3import android.app.Activity;
4import android.content.Intent;
5import android.util.Log;
6import android.annotation.TargetApi;
7import android.net.Uri;
8import android.os.Build;
9
10import org.apache.cordova.CallbackContext;
11import org.apache.cordova.CordovaPlugin;
12import org.apache.cordova.PluginResult;
13
14import org.json.JSONArray;
15import org.json.JSONException;
16import org.json.JSONObject;
17
18import java.util.ArrayList;
19import java.util.Iterator;
20
21import android.os.Bundle;
22import android.content.SharedPreferences;
23import android.app.Application;
24
25import io.branch.indexing.BranchUniversalObject;
26import io.branch.referral.Branch;
27import io.branch.referral.BranchUtil;
28import io.branch.referral.PrefHelper;
29import io.branch.referral.BranchError;
30import io.branch.referral.BranchViewHandler;
31import io.branch.referral.SharingHelper;
32import io.branch.referral.util.BRANCH_STANDARD_EVENT;
33import io.branch.referral.util.BranchEvent;
34import io.branch.referral.util.CommerceEvent;
35import io.branch.referral.util.CurrencyType;
36import io.branch.referral.util.Product;
37import io.branch.referral.util.ProductCategory;
38import io.branch.referral.util.ShareSheetStyle;
39import com.google.firebase.analytics.FirebaseAnalytics;
40
41import io.branch.referral.ServerRequestGetLATD.BranchLastAttributedTouchDataListener;
42import io.branch.referral.ServerRequestGetCPID.BranchCrossPlatformIdListener;
43import io.branch.referral.util.BranchCPID;
44
45public class BranchSDK extends CordovaPlugin {
46
47 static class BranchLinkProperties extends io.branch.referral.util.LinkProperties {
48 }
49
50 // Standard Debugging Variables
51 private static final String LCAT = "CordovaBranchSDK";
52 // todo pick up plugin version dynamically
53 private static final String BRANCH_PLUGIN_VERSION = "4.1.3";
54
55 // Private Method Properties
56 private ArrayList<BranchUniversalObjectWrapper> branchObjectWrappers;
57 private Activity activity;
58 private Branch instance;
59 private String deepLinkUrl;
60
61 /**
62 * Class Constructor
63 */
64 public BranchSDK() {
65
66 this.activity = null;
67 this.instance = null;
68 this.branchObjectWrappers = new ArrayList<BranchUniversalObjectWrapper>();
69
70 }
71
72 /**
73 * Called after plugin construction and fields have been initialized.
74 */
75 @Override
76 protected void pluginInitialize() {
77
78 this.activity = this.cordova.getActivity();
79 Branch.disableInstantDeepLinking(true);
80 BranchUtil.setPluginType(BranchUtil.PluginType.CordovaIonic);
81 BranchUtil.setPluginVersion(BRANCH_PLUGIN_VERSION);
82 if (this.instance == null) {
83 this.instance = Branch.getAutoInstance(this.activity.getApplicationContext());
84 }
85 }
86
87 /**
88 * Called when the activity receives a new intent.
89 */
90 public void onNewIntent(Intent intent) {
91 intent.putExtra("branch_force_new_session", true);
92 this.activity.setIntent(intent);
93 }
94
95 /**
96 * Handle depreciated call to sendJavaScript for more recent method
97 */
98 @TargetApi(Build.VERSION_CODES.KITKAT)
99 private void sendJavascript(final String javascript) {
100 webView.getView().post(new Runnable() {
101 @Override
102 public void run() {
103 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
104 webView.sendJavascript(javascript);
105 } else {
106 webView.loadUrl("javascript:" + javascript);
107 }
108 }
109 });
110 }
111
112 /**
113 * <p>
114 * cordova.exec() method reference.
115 * All exec() calls goes to this part.
116 * </p>
117 *
118 * @param action A {@link String} value method to be executed.
119 * @param args A {@link JSONArray} value parameters passed along with the action param.
120 * @param callbackContext A {@link CallbackContext} function passed for executing callbacks.
121 */
122 @Override
123 public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
124
125 Log.d(LCAT, "Execute: " + action);
126
127 Runnable r = new RunnableThread(action, args, callbackContext);
128
129 if (action.equals("setDebug")) {
130 cordova.getActivity().runOnUiThread(r);
131 return true;
132 } else if (action.equals("setCookieBasedMatching")) {
133 cordova.getActivity().runOnUiThread(r);
134 return true;
135 } else if (action.equals("disableTracking")) {
136 cordova.getActivity().runOnUiThread(r);
137 return true;
138 } else if (action.equals("initSession")) {
139 cordova.getActivity().runOnUiThread(r);
140 return true;
141 } else if (action.equals("setRequestMetadata")) {
142 cordova.getActivity().runOnUiThread(r);
143 return true;
144 } else {
145 if (this.instance != null) {
146 if (action.equals("setIdentity")) {
147 cordova.getActivity().runOnUiThread(r);
148 return true;
149 } else if (action.equals("userCompletedAction")) {
150 if (args.length() < 1 && args.length() > 2) {
151 callbackContext.error(String.format("Parameter mismatched. 1-2 is required but %d is given", args.length()));
152 return false;
153 }
154 cordova.getActivity().runOnUiThread(r);
155 return true;
156 } else if (action.equals("sendCommerceEvent")) {
157 if (args.length() < 1 && args.length() > 2) {
158 callbackContext.error(String.format("Parameter mismatched. 1-2 is required but %d is given", args.length()));
159 return false;
160 }
161 cordova.getActivity().runOnUiThread(r);
162 return true;
163 } else if (action.equals("sendBranchEvent")) {
164 if (args.length() < 1 && args.length() > 2) {
165 callbackContext.error(String.format("Parameter mismatched. 1-2 is required but %d is given", args.length()));
166 return false;
167 }
168 cordova.getActivity().runOnUiThread(r);
169 return true;
170 } else if (action.equals("getFirstReferringParams")) {
171 cordova.getActivity().runOnUiThread(r);
172 return true;
173 } else if (action.equals("getLatestReferringParams")) {
174 cordova.getActivity().runOnUiThread(r);
175 return true;
176 } else if (action.equals("logout")) {
177 cordova.getActivity().runOnUiThread(r);
178 return true;
179 } else if (action.equals("loadRewards")) {
180 cordova.getActivity().runOnUiThread(r);
181 return true;
182 } else if (action.equals("redeemRewards")) {
183 if (args.length() < 1 && args.length() > 2) {
184 callbackContext.error(String.format("Parameter mismatched. 1-2 is required but %d is given", args.length()));
185 return false;
186 }
187 cordova.getActivity().runOnUiThread(r);
188 return true;
189 } else if (action.equals("getCreditHistory")) {
190 cordova.getActivity().runOnUiThread(r);
191 return true;
192 } else if (action.equals("createBranchUniversalObject")) {
193 if (args.length() != 1) {
194 callbackContext.error(String.format("Parameter mismatched. 1 is required but %d is given", args.length()));
195 return false;
196 }
197 cordova.getActivity().runOnUiThread(r);
198 return true;
199
200 } else if (action.equals("crossPlatformIds")) {
201 cordova.getActivity().runOnUiThread(r);
202 return true;
203
204 } else if (action.equals("lastAttributedTouchData")) {
205 cordova.getActivity().runOnUiThread(r);
206 return true;
207
208 } else if (action.equals(("generateShortUrl"))) {
209 if (args.length() != 3) {
210 callbackContext.error(String.format("Parameter mismatched. 3 is required but %d is given", args.length()));
211 return false;
212 }
213 cordova.getActivity().runOnUiThread(r);
214 return true;
215 } else if (action.equals("registerView")) {
216 if (args.length() != 1) {
217 callbackContext.error(String.format("Parameter mismatched. 1 is required but %d is given", args.length()));
218 return false;
219 }
220 cordova.getActivity().runOnUiThread(r);
221 return true;
222 } else if (action.equals("showShareSheet")) {
223 if (args.length() < 3) {
224 callbackContext.error(String.format("Parameter mismatched. 3 is required but %d is given", args.length()));
225 return false;
226 }
227 cordova.getActivity().runOnUiThread(r);
228 return true;
229 } else if (action.equals("onShareLinkDialogLaunched")) {
230
231 BranchUniversalObjectWrapper branchObjWrapper = (BranchUniversalObjectWrapper) branchObjectWrappers.get(args.getInt(0));
232 branchObjWrapper.onShareLinkDialogLaunched = callbackContext;
233
234 branchObjectWrappers.set(args.getInt(0), branchObjWrapper);
235
236 } else if (action.equals("onShareLinkDialogDismissed")) {
237
238 BranchUniversalObjectWrapper branchObjWrapper = (BranchUniversalObjectWrapper) branchObjectWrappers.get(args.getInt(0));
239 branchObjWrapper.onShareLinkDialogDismissed = callbackContext;
240
241 branchObjectWrappers.set(args.getInt(0), branchObjWrapper);
242
243 } else if (action.equals("onLinkShareResponse")) {
244
245 BranchUniversalObjectWrapper branchObjWrapper = (BranchUniversalObjectWrapper) branchObjectWrappers.get(args.getInt(0));
246 branchObjWrapper.onLinkShareResponse = callbackContext;
247
248 branchObjectWrappers.set(args.getInt(0), branchObjWrapper);
249
250 } else if (action.equals("onChannelSelected")) {
251
252 BranchUniversalObjectWrapper branchObjWrapper = (BranchUniversalObjectWrapper) branchObjectWrappers.get(args.getInt(0));
253 branchObjWrapper.onChannelSelected = callbackContext;
254
255 branchObjectWrappers.set(args.getInt(0), branchObjWrapper);
256
257 }
258
259 return true;
260
261 } else {
262 callbackContext.error("Branch instance not set. Please execute initSession() first.");
263 }
264 }
265
266 return false;
267
268 }
269
270 @Override
271 public void onStart() {
272 super.onStart();
273
274 Activity context = new Activity();
275 // Branch init
276 Branch.getInstance().initSession(new Branch.BranchReferralInitListener() {
277 @Override
278 public void onInitFinished(JSONObject referringParams, BranchError error) {
279 if (error == null) {
280 if (referringParams != null) {
281 try {
282 // check if the session is from a Branch link
283 if (referringParams.getBoolean("+clicked_branch_link")) {
284
285 // create Firebase Analytics instance
286 FirebaseAnalytics firebaseAnalytics = FirebaseAnalytics
287 .getInstance(context.getApplicationContext());
288 Bundle bundle = new Bundle();
289
290 bundle.putBoolean("clicked_branch_link",
291 referringParams.getBoolean("+clicked_branch_link"));
292 // get the click timestamp
293 bundle.putString("click_timestamp",
294 referringParams.getString("+click_timestamp"));
295 // get the link OG title
296 bundle.putString("link_title",
297 referringParams.getString("$og_title"));
298 // get the link OG image
299 bundle.putString("link_image",
300 referringParams.getString("$og_image_url"));
301 // get the link campaign
302 bundle.putString("utm_campaign",
303 referringParams.getString("~campaign"));
304 // get the link channel
305 bundle.putString("utm_medium",
306 referringParams.getString("channel"));
307 // get the link feature
308 bundle.putString("utm_source",
309 referringParams.getString("~feature"));
310
311 // you can use the local shared preference to detect if this is an install session or open session as below
312 SharedPreferences sharedPreferences = context.getApplicationContext()
313 .getSharedPreferences("local_sharefpref",
314 context.MODE_PRIVATE);
315 SharedPreferences.Editor editor = sharedPreferences.edit();
316 boolean isFirstSession = sharedPreferences
317 .getBoolean("is_first_session", true);
318 if (isFirstSession) {
319 editor.putBoolean("is_first_session", false);
320 editor.apply();
321 }
322
323 // check if the session is install or open
324 String eventName =
325 isFirstSession ? "branch_install" : "branch_open";
326
327 // log the event to the firebase
328 firebaseAnalytics.logEvent(eventName, bundle);
329 }
330 } catch (JSONException ignore) {
331 }
332 }
333 }
334 }
335 }, this.getIntent().getData(), this);
336 }
337
338 public void crossPlatformIds(CallbackContext callbackContext) {
339 // stub call from known issue with caching
340 // this.instance.getCrossPlatformIds(new BranchCPIDListener(callbackContext));
341 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, false));
342 }
343
344 public void lastAttributedTouchData(CallbackContext callbackContext) {
345 // stub call from known issue with caching
346 // this.instance.getLastAttributedTouchData(new BranchLATDListener(callbackContext), 30);
347 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, false));
348 }
349
350 //////////////////////////////////////////////////
351 //----------- CLASS PRIVATE METHODS ------------//
352 //////////////////////////////////////////////////
353
354 /**
355 * <p>Initialises a session with the Branch API, assigning a {@link Branch.BranchUniversalReferralInitListener}
356 * to perform an action upon successful initialisation.</p>
357 *
358 * @param callbackContext A callback to execute at the end of this method
359 */
360 private void initSession(CallbackContext callbackContext) {
361
362 this.activity = this.cordova.getActivity();
363
364 Uri data = activity.getIntent().getData();
365
366 if (data != null && data.isHierarchical()) {
367 this.deepLinkUrl = data.toString();
368 }
369
370 this.instance.initSession(new SessionListener(callbackContext), data, activity);
371 }
372
373 /**
374 * <p>This method should be called if you know that a different person is about to use the app. For example,
375 * if you allow users to log out and let their friend use the app, you should call this to notify Branch
376 * to create a new user for this device. This will clear the first and latest params, as a new session is created.</p>
377 *
378 * @param callbackContext A callback to execute at the end of this method
379 */
380 private void logout(CallbackContext callbackContext) {
381
382 this.instance.logout(new LogoutStatusListener(callbackContext));
383
384 }
385
386 /**
387 * <p>Redeems the specified number of credits from the "default" bucket, if there are sufficient
388 * credits within it. If the number to redeem exceeds the number available in the bucket, all of
389 * the available credits will be redeemed instead.</p>
390 *
391 * @param value An {@link Integer} specifying the number of credits to attempt to redeem from
392 * the bucket.
393 * @param callbackContext A callback to execute at the end of this method
394 */
395 private void redeemRewards(final int value, CallbackContext callbackContext) {
396
397 this.instance.redeemRewards(value, new RedeemRewardsListener(callbackContext));
398
399 }
400
401 /**
402 * <p>Redeems the specified number of credits from the "default" bucket, if there are sufficient
403 * credits within it. If the number to redeem exceeds the number available in the bucket, all of
404 * the available credits will be redeemed instead.</p>
405 *
406 * @param value An {@link Integer} specifying the number of credits to attempt to redeem from
407 * the bucket.
408 * @param bucket The name of the bucket to remove the credits from.
409 * @param callbackContext A callback to execute at the end of this method
410 */
411 private void redeemRewards(int value, String bucket, CallbackContext callbackContext) {
412
413 this.instance.redeemRewards(bucket, value, new RedeemRewardsListener(callbackContext));
414
415 }
416
417 /**
418 * <p>Retrieves rewards for the current session, with a callback to perform a predefined
419 * action following successful report of state change. You'll then need to call getCredits
420 * in the callback to update the credit totals in your UX.</p>
421 *
422 * @param callbackContext A callback to execute at the end of this method
423 * @param bucket Load reward of a specific bucket
424 */
425 private void loadRewards(String bucket, CallbackContext callbackContext) {
426
427 this.instance.loadRewards(new LoadRewardsListener(bucket, callbackContext, this.instance));
428
429 }
430
431 /**
432 * <p>Retrieves rewards for the current session, with a callback to perform a predefined
433 * action following successful report of state change. You'll then need to call getCredits
434 * in the callback to update the credit totals in your UX.</p>
435 *
436 * @param callbackContext A callback to execute at the end of this method
437 */
438 private void loadRewards(CallbackContext callbackContext) {
439
440 this.instance.loadRewards(new LoadRewardsListener(callbackContext, this.instance));
441
442 }
443
444 /**
445 * <p>Returns the parameters associated with the link that referred the session. If a user
446 * clicks a link, and then opens the app, initSession will return the paramters of the link
447 * and then set them in as the latest parameters to be retrieved by this method. By default,
448 * sessions persist for the duration of time that the app is in focus. For example, if you
449 * minimize the app, these parameters will be cleared when closeSession is called.</p>
450 *
451 * @param callbackContext A callback to execute at the end of this method
452 * @return A {@link JSONObject} containing the latest referring parameters as
453 * configured locally.
454 */
455 private void getLatestReferringParams(CallbackContext callbackContext) {
456
457 JSONObject sessionParams = this.instance.getLatestReferringParams();
458
459 if (sessionParams == null || sessionParams.length() == 0) {
460 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, /* send boolean: false as the data */ false));
461 } else {
462 Log.d(LCAT, sessionParams.toString());
463 callbackContext.success(sessionParams);
464 }
465
466 }
467
468 /**
469 * <p>Returns the parameters associated with the link that referred the user. This is only set once,
470 * the first time the user is referred by a link. Think of this as the user referral parameters.
471 * It is also only set if isReferrable is equal to true, which by default is only true
472 * on a fresh install (not upgrade or reinstall). This will change on setIdentity (if the
473 * user already exists from a previous device) and logout.</p>
474 *
475 * @param callbackContext A callback to execute at the end of this method
476 */
477 private void getFirstReferringParams(CallbackContext callbackContext) {
478
479 JSONObject installParams = this.instance.getFirstReferringParams();
480
481 if (installParams == null || installParams.length() == 0) {
482 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, /* send boolean: false as the data */ false));
483 } else {
484 Log.d(LCAT, installParams.toString());
485 callbackContext.success(installParams);
486 }
487
488 }
489
490 /**
491 * <p>
492 * Create a BranchUniversalObject with the given content.
493 * </p>
494 *
495 * @param options A {@link JSONObject} value to set for the branch universal object properties.
496 * @return A {@link JSONObject} value of BranchUniversalObject instance.
497 */
498 private void createBranchUniversalObject(JSONObject options, CallbackContext callbackContext) throws JSONException {
499
500 BranchUniversalObject branchObj = new BranchUniversalObject();
501
502 // Set object properties
503 // Facebook Properties
504 if (options.has("canonicalIdentifier")) {
505 branchObj.setCanonicalIdentifier(options.getString("canonicalIdentifier"));
506 }
507 if (options.has("title")) {
508 branchObj.setTitle(options.getString("title"));
509 }
510 if (options.has("contentDescription")) {
511 branchObj.setContentDescription(options.getString("contentDescription"));
512 }
513 if (options.has("contentImageUrl")) {
514 branchObj.setContentImageUrl(options.getString("contentImageUrl"));
515 }
516 if (options.has("contentType")) {
517 branchObj.setContentType(options.getString("contentType"));
518 }
519
520 // Set content visibility
521 if (options.has("contentIndexingMode")) {
522 if (options.getString("contentIndexingMode").equals("private")) {
523 branchObj.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PRIVATE);
524 } else {
525 branchObj.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC);
526 }
527 }
528
529 // Add custom keys/values to the deep link data
530 if (options.has("contentMetadata")) {
531
532 JSONObject contentMetaData = options.getJSONObject("contentMetadata");
533 Iterator<?> keys = contentMetaData.keys();
534
535 while (keys.hasNext()) {
536 String key = (String) keys.next();
537 String value = contentMetaData.optString(key);
538 Log.d(LCAT, contentMetaData.getString(key));
539 branchObj.addContentMetadata(key, value);
540 }
541 }
542
543 BranchUniversalObjectWrapper branchObjWrapper = new BranchUniversalObjectWrapper(branchObj);
544
545 this.branchObjectWrappers.add(branchObjWrapper);
546 JSONObject response = new JSONObject();
547 response.put("message", "Success");
548 response.put("branchUniversalObjectId", this.branchObjectWrappers.size() - 1);
549
550 callbackContext.success(response);
551
552 }
553
554 /**
555 * Display a popup of the share sheet.
556 *
557 * @param instanceIdx The instance index from branchObjects array
558 * @param options A {@link JSONObject} value to set URL options.
559 * @param controlParams A {@link JSONObject} value to set the URL control parameters.
560 */
561 private void showShareSheet(int instanceIdx, JSONObject options, JSONObject controlParams, JSONObject strings) throws JSONException {
562
563 ShareSheetStyle shareSheetStyle = new ShareSheetStyle(this.activity, strings.getString("shareTitle"), strings.getString("shareText"))
564 .setCopyUrlStyle(this.activity.getResources().getDrawable(android.R.drawable.ic_menu_send), strings.getString("copyToClipboard"), strings.getString("clipboardSuccess"))
565 .setMoreOptionStyle(this.activity.getResources().getDrawable(android.R.drawable.ic_menu_search), strings.getString("more"))
566 .addPreferredSharingOption(SharingHelper.SHARE_WITH.FACEBOOK)
567 .addPreferredSharingOption(SharingHelper.SHARE_WITH.EMAIL)
568 .addPreferredSharingOption(SharingHelper.SHARE_WITH.MESSAGE)
569 .addPreferredSharingOption(SharingHelper.SHARE_WITH.TWITTER)
570 .setAsFullWidthStyle(true)
571 .setSharingTitle(strings.getString("shareWith"));
572
573 BranchUniversalObjectWrapper branchObjWrapper = (BranchUniversalObjectWrapper) this.branchObjectWrappers.get(instanceIdx);
574 BranchLinkProperties linkProperties = createLinkProperties(options, controlParams);
575 BranchUniversalObject branchObj = branchObjWrapper.branchUniversalObj;
576
577 branchObj.showShareSheet(this.activity, linkProperties, shareSheetStyle,
578 new ShowShareSheetListener(branchObjWrapper.onShareLinkDialogLaunched, branchObjWrapper.onShareLinkDialogDismissed, branchObjWrapper.onLinkShareResponse, branchObjWrapper.onChannelSelected));
579
580 }
581
582 /**
583 * Generates a share link.
584 *
585 * @param options A {@link JSONObject} value to set URL options.
586 * @param controlParams A {@link JSONObject} value to set the URL control parameters.
587 * @return A {@link io.branch.referral.util.LinkProperties} value.
588 */
589 private BranchLinkProperties createLinkProperties(JSONObject options, JSONObject controlParams) throws JSONException {
590
591 Log.d(LCAT, "Creating link properties");
592
593 BranchLinkProperties linkProperties = new BranchLinkProperties();
594
595 // Add link properties
596 if (options.has("feature")) {
597 linkProperties.setFeature(options.getString("feature"));
598 }
599 if (options.has("alias")) {
600 linkProperties.setAlias(options.getString("alias"));
601 }
602 if (options.has("channel")) {
603 linkProperties.setChannel(options.getString("channel"));
604 }
605 if (options.has("stage")) {
606 linkProperties.setStage(options.getString("stage"));
607 }
608 if (options.has("campaign")) {
609 linkProperties.setCampaign(options.getString("campaign"));
610 }
611 if (options.has("duration")) {
612 linkProperties.setDuration(options.getInt("duration"));
613 }
614 if (options.has("tags")) {
615 JSONArray array = (JSONArray) options.get("tags");
616 if (array != null) {
617 for (int i = 0; i < array.length(); i++) {
618 linkProperties.addTag(array.get(i).toString());
619 }
620 }
621 }
622
623 Log.d(LCAT, "Adding control parameters:");
624
625 // Add and iterate control parameters properties
626 Iterator<?> keys = controlParams.keys();
627
628 while (keys.hasNext()) {
629 String key = keys.next().toString();
630
631 Log.d(LCAT, String.format("key: %s", key));
632
633 linkProperties.addControlParameter(key, controlParams.getString(key));
634 }
635
636 return linkProperties;
637
638 }
639
640 /**
641 * Mark the content referred by this object as viewed. This increment the view count of the contents referred by this object.
642 *
643 * @param instanceIdx The instance index from branchObjects array
644 */
645 private void registerView(int instanceIdx, CallbackContext callbackContext) {
646
647 BranchUniversalObjectWrapper branchUniversalWrapper = (BranchUniversalObjectWrapper) this.branchObjectWrappers.get(instanceIdx);
648
649 branchUniversalWrapper.branchUniversalObj.registerView(new RegisterViewStatusListener(callbackContext));
650
651 }
652
653 /**
654 * Generate a URL.
655 *
656 * @param instanceIdx The instance index from branchObjects array
657 * @param options A {@link JSONObject} value to set URL options.
658 * @param controlParams A {@link JSONObject} value to set the URL control parameters.
659 */
660 private void generateShortUrl(int instanceIdx, JSONObject options, JSONObject controlParams, CallbackContext callbackContext) throws JSONException {
661
662 BranchLinkProperties linkProperties = createLinkProperties(options, controlParams);
663
664 BranchUniversalObjectWrapper branchUniversalWrapper = (BranchUniversalObjectWrapper) this.branchObjectWrappers.get(instanceIdx);
665
666 branchUniversalWrapper.branchUniversalObj.generateShortUrl(this.activity, linkProperties, new GenerateShortUrlListener(callbackContext));
667
668 }
669
670 /**
671 * <p>Sets the cookie based matching for all incoming requests.</p>
672 * <p>If you want cookie based matching, call this <b>before</b> initUserSession</p>
673 *
674 * @param linkDomain A {@link String} value to of the link domain for cookie based matching.
675 * @param callbackContext A callback to execute at the end of this method
676 */
677 private void setCookieBasedMatching(String linkDomain, CallbackContext callbackContext) {
678
679 this.activity = this.cordova.getActivity();
680
681 if (linkDomain != null) {
682 Branch.enableCookieBasedMatching(linkDomain);
683 }
684
685 callbackContext.success("Success");
686 }
687
688 /**
689 * <p>Sets the library to function in debug mode, enabling logging of all requests.</p>
690 * <p>If you want to flag debug, call this <b>before</b> initUserSession</p>
691 *
692 * @param isEnable A {@link Boolean} value to enable/disable debugging mode for the app.
693 * @param callbackContext A callback to execute at the end of this method
694 */
695 private void setDebug(boolean isEnable, CallbackContext callbackContext) {
696 this.activity = this.cordova.getActivity();
697 Branch.enableDebugMode();
698 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, isEnable));
699 }
700
701 /**
702 * <p>Disables tracking for GDPR compliance.</p>
703 * <p>Can flag at any time.</p>
704 * <p>Limits all Branch network requests and forces long link generation.</p>
705 *
706 * @param isEnable A {@link Boolean} value to enable/disable debugging mode for the app.
707 * @param callbackContext A callback to execute at the end of this method
708 */
709 private void disableTracking(boolean isEnable, CallbackContext callbackContext) {
710 this.activity = this.cordova.getActivity();
711
712 this.instance.disableTracking(isEnable);
713 callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, isEnable));
714 }
715
716 /**
717 * <p>Identifies the current user to the Branch API by supplying a unique
718 * identifier as a {@link String} value.</p>
719 *
720 * @param newIdentity A {@link String} value containing the unique identifier of the user.
721 * @param callbackContext A callback to execute at the end of this method
722 */
723 private void setIdentity(String newIdentity, CallbackContext callbackContext) {
724
725 this.instance.setIdentity(newIdentity, new SetIdentityListener(callbackContext));
726
727 }
728
729 /**
730 * <p>Allow Branch SDK to pass the user's Mixpanel distinct id to our servers. Branch will then pass that Distinct ID to Mixpanel when logging any event.</p>
731 *
732 * @param token A {@link String} value containing the unique identifier of the Mixpanel user.
733 * @param callbackContext A callback to execute at the end of this method
734 */
735 private void setRequestMetadata(String key, String val, CallbackContext callbackContext) {
736
737 Branch.getInstance().setRequestMetadata(key, val);
738
739 callbackContext.success("Success");
740
741 }
742
743 /**
744 * <p>A void call to indicate that the user has performed a specific action and for that to be
745 * reported to the Branch API.</p>
746 *
747 * @param action A {@link String} value to be passed as an action that the user has carried out.
748 * For example "logged in" or "registered".
749 * @param callbackContext A callback to execute at the end of this method
750 */
751 private void userCompletedAction(String action, CallbackContext callbackContext) {
752
753 this.instance.userCompletedAction(action);
754
755 callbackContext.success("Success");
756
757 }
758
759 /**
760 * <p>A void call to indicate that the user has performed a specific action and for that to be
761 * reported to the Branch API.</p>
762 *
763 * @param action A {@link String} value to be passed as an action that the user has carried
764 * out. For example "logged in" or "registered".
765 * @param metaData A {@link JSONObject} containing app-defined meta-data to be attached to a
766 * user action that has just been completed.
767 * @param callbackContext A callback to execute at the end of this method
768 */
769 private void userCompletedAction(String action, JSONObject metaData, CallbackContext callbackContext) {
770
771 this.instance.userCompletedAction(action, metaData);
772
773 callbackContext.success("Success");
774
775 }
776
777 /**
778 * <p>A void call to indicate that the user has performed a specific commerce event and for that to be
779 * reported to the Branch API.</p>
780 *
781 * @param action A {@link String} value to be passed as an commerce event that the user has
782 * carried out.
783 * @param metaData A {@link JSONObject} containing app-defined meta-data to be attached to a
784 * user action that has just been completed.
785 * @param callbackContext A callback to execute at the end of this method
786 */
787 private void sendCommerceEvent(JSONObject action, JSONObject metaData, CallbackContext callbackContext) throws JSONException {
788
789 CommerceEvent commerce = new CommerceEvent();
790 Iterator<String> keys = action.keys();
791 while (keys.hasNext()) {
792 String key = keys.next();
793 String val;
794 try {
795 val = action.getString(key);
796 } catch (JSONException e) {
797 e.printStackTrace();
798 callbackContext.error("Invalid key-value for " + key);
799 return;
800 }
801 if (key.equals("revenue")) {
802 commerce.setRevenue(Double.parseDouble(val));
803 } else if (key.equals("currency")) {
804 commerce.setCurrencyType(CurrencyType.values()[Integer.parseInt(val)]);
805 } else if (key.equals("transactionID")) {
806 commerce.setTransactionID(val);
807 } else if (key.equals("coupon")) {
808 commerce.setCoupon(val);
809 } else if (key.equals("shipping")) {
810 commerce.setShipping(Double.parseDouble(val));
811 } else if (key.equals("tax")) {
812 commerce.setTax(Double.parseDouble(val));
813 } else if (key.equals("affiliation")) {
814 commerce.setAffiliation(val);
815 } else if (key.equals("products")) {
816 JSONArray products = new JSONArray();
817 try {
818 products = action.getJSONArray(key);
819 } catch (JSONException e) {
820 e.printStackTrace();
821 callbackContext.error("Invalid key-value for " + key);
822 return;
823 }
824 for (int i = 0; i < products.length(); ++i) {
825 Product product = new Product();
826 JSONObject item = products.getJSONObject(i);
827 keys = item.keys();
828 while (keys.hasNext()) {
829 key = keys.next();
830 try {
831 val = item.getString(key);
832 } catch (JSONException e) {
833 e.printStackTrace();
834 callbackContext.error("Invalid key-value for product for " + key);
835 return;
836 }
837 if (key.equals("sku")) {
838 product.setSku(val);
839 } else if (key.equals("name")) {
840 product.setName(val);
841 } else if (key.equals("price")) {
842 product.setPrice(Double.parseDouble(val));
843 } else if (key.equals("quantity")) {
844 product.setQuantity(Integer.parseInt(val));
845 } else if (key.equals("brand")) {
846 product.setBrand(val);
847 } else if (key.equals("category")) {
848 product.setCategory(ProductCategory.values()[Integer.parseInt(val)]);
849 } else if (key.equals("variant")) {
850 product.setVariant(val);
851 }
852 }
853 commerce.addProduct(product);
854 }
855 }
856 }
857
858 this.instance.sendCommerceEvent(commerce, metaData, new BranchViewEventsListener(callbackContext));
859
860 }
861
862 public void sendBranchEvent(String eventName, JSONObject metaData, CallbackContext callbackContext) throws JSONException {
863
864 BranchEvent event;
865 try {
866 BRANCH_STANDARD_EVENT standardEvent = BRANCH_STANDARD_EVENT.valueOf(eventName);
867 event = new BranchEvent(standardEvent);
868 } catch(IllegalArgumentException e) {
869 event = new BranchEvent(eventName);
870 }
871
872 Iterator < String > keys = metaData.keys();
873 while (keys.hasNext()) {
874 String key = keys.next();
875 if (key.equals("revenue")) {
876 event.setRevenue(Double.parseDouble(metaData.getString("revenue")));
877 } else if (key.equals("currency")) {
878 String currencyString = metaData.getString("currency");
879 CurrencyType currency = CurrencyType.getValue(currencyString);
880 if (currency != null) {
881 event.setCurrency(currency);
882 }
883 else {
884 Log.d(LCAT, "Invalid currency " + currencyString);
885 }
886 } else if (key.equals("transactionID")) {
887 event.setTransactionID(metaData.getString("transactionID"));
888 } else if (key.equals("coupon")) {
889 event.setCoupon(metaData.getString("coupon"));
890 } else if (key.equals("shipping")) {
891 event.setShipping(Double.parseDouble(metaData.getString("shipping")));
892 } else if (key.equals("tax")) {
893 event.setTax(Double.parseDouble(metaData.getString("tax")));
894 } else if (key.equals("affiliation")) {
895 event.setAffiliation(metaData.getString("affiliation"));
896 } else if (key.equals("description")) {
897 event.setDescription(metaData.getString("description"));
898 } else if (key.equals("searchQuery")) {
899 event.setSearchQuery(metaData.getString("searchQuery"));
900 } else if (key.equals("customerEventAlias")) {
901 event.setCustomerEventAlias(metaData.getString("customerEventAlias"));
902 } else if (key.equals("customData")) {
903 JSONObject customData = metaData.getJSONObject("customData");
904 keys = customData.keys();
905
906 while (keys.hasNext()) {
907 String keyValue = (String) keys.next();
908 event.addCustomDataProperty(keyValue, customData.getString(keyValue));
909 }
910 }
911
912 }
913 event.logEvent(this.activity);
914 //callbackContext.success();
915 }
916
917 /**
918 * <p>Gets the credit history of the specified bucket and triggers a callback to handle the
919 * response.</p>
920 *
921 * @param callbackContext A callback to execute at the end of this method
922 */
923 private void getCreditHistory(CallbackContext callbackContext) {
924
925 this.instance.getCreditHistory(new CreditHistoryListener(callbackContext));
926
927 }
928
929 /**
930 * @access protected
931 * @class BranchUniversalObjectWrapper
932 */
933 protected class BranchUniversalObjectWrapper {
934
935 public BranchUniversalObject branchUniversalObj;
936 public CallbackContext onShareLinkDialogDismissed;
937 public CallbackContext onShareLinkDialogLaunched;
938 public CallbackContext onLinkShareResponse;
939 public CallbackContext onChannelSelected;
940
941 /**
942 * @param branchUniversalObj branchUniversalObj
943 * @constructor
944 */
945 public BranchUniversalObjectWrapper(BranchUniversalObject branchUniversalObj) {
946 this.branchUniversalObj = branchUniversalObj;
947 this.onShareLinkDialogDismissed = null;
948 this.onShareLinkDialogLaunched = null;
949 this.onLinkShareResponse = null;
950 this.onChannelSelected = null;
951 }
952
953 }
954
955 //////////////////////////////////////////////////
956 //----------- INNER CLASS LISTENERS ------------//
957 //////////////////////////////////////////////////
958
959 protected class BranchCPIDListener implements BranchCrossPlatformIdListener {
960 private CallbackContext _callbackContext;
961
962 public BranchCPIDListener(CallbackContext callbackContext) {
963 this._callbackContext = callbackContext;
964 }
965
966 @Override
967 public void onDataFetched(BranchCPID branchCPID, BranchError error) {
968 if (error != null) {
969 Log.d(LCAT, "CPID unavailable");
970 this._callbackContext.error("CPID unavailable");
971 } else {
972
973 JSONObject jsonObject = new JSONObject();
974 try {
975 jsonObject.put("developer_identity", branchCPID.getDeveloperIdentity());
976 jsonObject.put("cross_platform_id", branchCPID.getCrossPlatformID());
977 jsonObject.put("past_cross_platform_ids", branchCPID.getPastCrossPlatformIds());
978 jsonObject.put("prob_cross_platform_ids", branchCPID.getProbabilisticCrossPlatformIds());
979 } catch (JSONException e) {
980 // just send back and empty object on json error
981 jsonObject = new JSONObject();
982 }
983
984 Log.d(LCAT, jsonObject.toString());
985
986 PluginResult result = new PluginResult(PluginResult.Status.OK, jsonObject);
987 this._callbackContext.sendPluginResult(result);
988 }
989 }
990 }
991
992 protected class BranchLATDListener implements BranchLastAttributedTouchDataListener {
993 private CallbackContext _callbackContext;
994
995 public BranchLATDListener(CallbackContext callbackContext) {
996 this._callbackContext = callbackContext;
997 }
998
999 @Override
1000 public void onDataFetched(JSONObject jsonObject, BranchError error) {
1001 if (error != null) {
1002 Log.d(LCAT, "LATD unavailable");
1003 this._callbackContext.error("LATD unavailable");
1004 } else {
1005 Log.d(LCAT, jsonObject.toString());
1006
1007 PluginResult result = new PluginResult(PluginResult.Status.OK, jsonObject);
1008 this._callbackContext.sendPluginResult(result);
1009 }
1010 }
1011 }
1012
1013 protected class BranchViewEventsListener implements BranchViewHandler.IBranchViewEvents {
1014
1015 private CallbackContext _callbackContext;
1016
1017 public BranchViewEventsListener(CallbackContext callbackContext) {
1018 callbackContext.success("Success");
1019 }
1020
1021 @Override
1022 public void onBranchViewVisible(String action, String branchViewID) {
1023
1024 }
1025
1026 @Override
1027 public void onBranchViewAccepted(String action, String branchViewID) {
1028
1029 }
1030
1031 @Override
1032 public void onBranchViewCancelled(String action, String branchViewID) {
1033
1034 }
1035
1036 @Override
1037 public void onBranchViewError(int errorCode, String errorMsg, String action) {
1038
1039 }
1040 }
1041
1042 protected class SessionListener implements Branch.BranchReferralInitListener {
1043 private CallbackContext _callbackContext;
1044
1045 public SessionListener(CallbackContext callbackContext) {
1046 this._callbackContext = callbackContext;
1047 }
1048
1049 //Listener that implements BranchReferralInitListener for initSession
1050 @Override
1051 public void onInitFinished(JSONObject referringParams, BranchError error) {
1052
1053 String out;
1054
1055 if (error == null && referringParams != null) {
1056 if (this._callbackContext != null) {
1057 this._callbackContext.success(referringParams);
1058 }
1059 } else {
1060 JSONObject message = new JSONObject();
1061 try {
1062 message.put("error", error.getMessage());
1063 } catch (JSONException e) {
1064 e.printStackTrace();
1065 }
1066 if (this._callbackContext != null) {
1067 this._callbackContext.error(message);
1068 }
1069 }
1070
1071
1072 }
1073
1074 }
1075
1076 protected class LogoutStatusListener implements Branch.LogoutStatusListener {
1077 private CallbackContext _callbackContext;
1078
1079 // Constructor that takes in a required callbackContext object
1080 public LogoutStatusListener(CallbackContext callbackContext) {
1081 this._callbackContext = callbackContext;
1082 }
1083
1084 /**
1085 * Called on finishing the the logout process
1086 *
1087 * @param loggedOut A {@link Boolean} which is set to true if logout succeeded
1088 * @param error An instance of {@link BranchError} to notify any error occurred during logout.
1089 * A null value is set if logout succeeded.
1090 */
1091 @Override
1092 public void onLogoutFinished(boolean loggedOut, BranchError error) {
1093 if (error == null) {
1094
1095 branchObjectWrappers = new ArrayList<BranchUniversalObjectWrapper>();
1096
1097 this._callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, /* send boolean: is logged out */ loggedOut));
1098
1099 } else {
1100
1101 Log.d(LCAT, "error on logout");
1102
1103 this._callbackContext.error(error.getMessage());
1104 }
1105 }
1106 }
1107
1108 protected class SetIdentityListener implements Branch.BranchReferralInitListener {
1109 private CallbackContext _callbackContext;
1110
1111 public SetIdentityListener(CallbackContext callbackContext) {
1112 this._callbackContext = callbackContext;
1113 }
1114
1115 //Listener that implements BranchReferralInitListener for setIdentity
1116 @Override
1117 public void onInitFinished(JSONObject referringParams, BranchError error) {
1118
1119 if (error == null) {
1120
1121 this._callbackContext.success(referringParams);
1122
1123 } else {
1124
1125 String errorMessage = error.getMessage();
1126
1127 Log.d(LCAT, errorMessage);
1128
1129 this._callbackContext.error(errorMessage);
1130
1131 }
1132
1133 }
1134
1135
1136 }
1137
1138 protected class RegisterViewStatusListener implements BranchUniversalObject.RegisterViewStatusListener {
1139
1140 private CallbackContext _callbackContext;
1141
1142 public RegisterViewStatusListener(CallbackContext callbackContext) {
1143 this._callbackContext = callbackContext;
1144 }
1145
1146 @Override
1147 public void onRegisterViewFinished(boolean registered, BranchError error) {
1148
1149 if (error == null) {
1150 this._callbackContext.success("Success");
1151 } else {
1152
1153 String errorMessage = error.getMessage();
1154
1155 Log.d(LCAT, errorMessage);
1156
1157 this._callbackContext.error(errorMessage);
1158 }
1159 }
1160 }
1161
1162 protected class LoadRewardsListener implements Branch.BranchReferralStateChangedListener {
1163 private CallbackContext _callbackContext;
1164 private Branch _instance;
1165 private String _bucket;
1166
1167 public LoadRewardsListener(String bucket, CallbackContext callbackContext, Branch instance) {
1168 this._callbackContext = callbackContext;
1169 this._instance = instance;
1170 this._bucket = bucket;
1171 }
1172
1173 public LoadRewardsListener(CallbackContext callbackContext, Branch instance) {
1174 this._callbackContext = callbackContext;
1175 this._instance = instance;
1176 this._bucket = "";
1177 }
1178
1179 // Listener that implements BranchReferralStateChangedListener for loadRewards
1180 @Override
1181 public void onStateChanged(boolean changed, BranchError error) {
1182 if (error == null) {
1183
1184 int credits = 0;
1185
1186 if (this._bucket.length() > 0) {
1187 credits = this._instance.getCreditsForBucket(this._bucket);
1188 } else {
1189 credits = this._instance.getCredits();
1190 }
1191
1192 this._callbackContext.success(credits);
1193
1194 } else {
1195
1196 String errorMessage = error.getMessage();
1197
1198 Log.d(LCAT, errorMessage);
1199
1200 this._callbackContext.error(errorMessage);
1201
1202 }
1203
1204 }
1205 }
1206
1207 protected class RedeemRewardsListener implements Branch.BranchReferralStateChangedListener {
1208 private CallbackContext _callbackContext;
1209
1210 // Constructor that takes in a required callbackContext object
1211 public RedeemRewardsListener(CallbackContext callbackContext) {
1212 this._callbackContext = callbackContext;
1213 }
1214
1215 // Listener that implements BranchReferralStateChangedListener for redeemRewards
1216 @Override
1217 public void onStateChanged(boolean changed, BranchError error) {
1218
1219 if (error == null) {
1220
1221 this._callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, /* send boolean: is changed */ changed));
1222
1223 } else {
1224
1225 String errorMessage = error.getMessage();
1226
1227 Log.d(LCAT, errorMessage);
1228
1229 this._callbackContext.error(errorMessage);
1230 }
1231 }
1232 }
1233
1234 protected class GenerateShortUrlListener implements Branch.BranchLinkCreateListener {
1235 private CallbackContext _callbackContext;
1236
1237 // Constructor that takes in a required callbackContext object
1238 public GenerateShortUrlListener(CallbackContext callbackContext) {
1239
1240 this._callbackContext = callbackContext;
1241
1242 }
1243
1244 @Override
1245 public void onLinkCreate(String url, BranchError error) {
1246
1247 JSONObject response = new JSONObject();
1248
1249 if (error == null || url != null) {
1250
1251 try {
1252 response.put("url", url);
1253 } catch (JSONException e) {
1254 e.printStackTrace();
1255 return;
1256 }
1257
1258 Log.d(LCAT, response.toString());
1259 this._callbackContext.success(response);
1260
1261 } else {
1262
1263 String errorMessage = error.getMessage();
1264
1265 Log.d(LCAT, errorMessage);
1266
1267 try {
1268 response.put("error", errorMessage);
1269 } catch (JSONException e) {
1270 e.printStackTrace();
1271 return;
1272 }
1273
1274 Log.d(LCAT, response.toString());
1275 this._callbackContext.error(response);
1276
1277 }
1278
1279 }
1280
1281 }
1282
1283 protected class ShowShareSheetListener implements Branch.BranchLinkShareListener {
1284
1285 private CallbackContext _onShareLinkDialogLaunched;
1286 private CallbackContext _onShareLinkDialogDismissed;
1287 private CallbackContext _onLinkShareResponse;
1288 private CallbackContext _onChannelSelected;
1289
1290 /**
1291 * @param onShareLinkDialogLaunched
1292 * @param onShareLinkDialogDismissed
1293 * @param onLinkShareResponse
1294 * @param onChannelSelected
1295 * @constructor
1296 */
1297 public ShowShareSheetListener(CallbackContext onShareLinkDialogLaunched, CallbackContext onShareLinkDialogDismissed, CallbackContext onLinkShareResponse, CallbackContext onChannelSelected) {
1298
1299 this._onShareLinkDialogDismissed = onShareLinkDialogDismissed;
1300 this._onShareLinkDialogLaunched = onShareLinkDialogLaunched;
1301 this._onLinkShareResponse = onLinkShareResponse;
1302 this._onChannelSelected = onChannelSelected;
1303
1304 }
1305
1306 @Override
1307 public void onShareLinkDialogLaunched() {
1308
1309 if (_onShareLinkDialogLaunched == null) {
1310 return;
1311 }
1312
1313 PluginResult result = new PluginResult(PluginResult.Status.OK);
1314
1315 result.setKeepCallback(true);
1316
1317 this._onShareLinkDialogLaunched.sendPluginResult(result);
1318
1319 }
1320
1321 @Override
1322 public void onShareLinkDialogDismissed() {
1323
1324 if (_onShareLinkDialogDismissed == null) {
1325 return;
1326 }
1327
1328 PluginResult result = new PluginResult(PluginResult.Status.OK);
1329
1330 result.setKeepCallback(true);
1331
1332 this._onShareLinkDialogDismissed.sendPluginResult(result);
1333
1334 }
1335
1336 @Override
1337 public void onLinkShareResponse(String sharedLink, String sharedChannel, BranchError error) {
1338
1339 if (_onLinkShareResponse == null) {
1340 return;
1341 }
1342
1343 JSONObject response = new JSONObject();
1344
1345 if (error == null) {
1346
1347 try {
1348 response.put("sharedLink", sharedLink);
1349 response.put("sharedChannel", sharedChannel);
1350 } catch (JSONException e) {
1351 e.printStackTrace();
1352 return;
1353 }
1354
1355 Log.d(LCAT, "sharedLink: " + sharedLink);
1356 Log.d(LCAT, "sharedChannel: " + sharedChannel);
1357 } else {
1358 String errorMessage = error.getMessage();
1359
1360 Log.d(LCAT, errorMessage);
1361
1362 try {
1363 response.put("error", errorMessage);
1364 } catch (JSONException e) {
1365 e.printStackTrace();
1366 return;
1367 }
1368 }
1369
1370 Log.d(LCAT, response.toString());
1371
1372 PluginResult result = new PluginResult(PluginResult.Status.OK, response);
1373
1374 result.setKeepCallback(true);
1375
1376 this._onLinkShareResponse.sendPluginResult(result);
1377
1378 }
1379
1380 @Override
1381 public void onChannelSelected(String channelName) {
1382
1383 if (_onChannelSelected == null) {
1384 return;
1385 }
1386
1387 JSONObject response = new JSONObject();
1388
1389 try {
1390 response.put("channelName", channelName);
1391 } catch (JSONException e) {
1392 e.printStackTrace();
1393 return;
1394 }
1395
1396 Log.d(LCAT, response.toString());
1397
1398 PluginResult result = new PluginResult(PluginResult.Status.OK, response);
1399
1400 result.setKeepCallback(true);
1401
1402 this._onChannelSelected.sendPluginResult(result);
1403
1404 }
1405 }
1406
1407 protected class CreditHistoryListener implements Branch.BranchListResponseListener {
1408 private CallbackContext _callbackContext;
1409
1410 // Constructor that takes in a required callbackContext object
1411 public CreditHistoryListener(CallbackContext callbackContext) {
1412 this._callbackContext = callbackContext;
1413 }
1414
1415 // Listener that implements BranchListResponseListener for getCreditHistory()
1416 @Override
1417 public void onReceivingResponse(JSONArray list, BranchError error) {
1418
1419 ArrayList<String> errors = new ArrayList<String>();
1420
1421 if (error == null) {
1422
1423 JSONArray data = new JSONArray();
1424
1425 if (list != null) {
1426
1427 for (int i = 0, limit = list.length(); i < limit; ++i) {
1428
1429 JSONObject entry;
1430
1431 try {
1432 entry = list.getJSONObject(i);
1433 data.put(entry);
1434 } catch (JSONException e) {
1435 e.printStackTrace();
1436 errors.add(e.getMessage());
1437 }
1438
1439 }
1440
1441 }
1442
1443 if (errors.size() > 0) {
1444 StringBuilder sb = new StringBuilder();
1445 for (String s : errors) {
1446 sb.append(s);
1447 sb.append("\n");
1448 }
1449 this._callbackContext.error(sb.toString());
1450 } else {
1451 this._callbackContext.success(data);
1452 }
1453 } else {
1454
1455 String errorMessage = error.getMessage();
1456
1457 Log.d(LCAT, errorMessage);
1458
1459 this._callbackContext.error(errorMessage);
1460
1461 }
1462 }
1463 }
1464
1465 protected class RunnableThread implements Runnable {
1466
1467 private String action;
1468 private JSONArray args;
1469 private CallbackContext callbackContext;
1470
1471 public RunnableThread(String action, JSONArray args, CallbackContext callbackContext) {
1472 this.callbackContext = callbackContext;
1473 this.action = action;
1474 this.args = args;
1475 }
1476
1477 public void run() {
1478 try {
1479 Log.d(LCAT, "Runnable: " + this.action);
1480
1481 if (this.action.equals("setDebug")) {
1482 setDebug(this.args.getBoolean(0), this.callbackContext);
1483 } else if (this.action.equals("setCookieBasedMatching")) {
1484 setCookieBasedMatching(this.args.getString(0), this.callbackContext);
1485 } else if (this.action.equals("disableTracking")) {
1486 disableTracking(this.args.getBoolean(0), this.callbackContext);
1487 } else if (this.action.equals("initSession")) {
1488 initSession(this.callbackContext);
1489 } else if (this.action.equals("setRequestMetadata")) {
1490 setRequestMetadata(this.args.getString(0), this.args.getString(1), this.callbackContext);
1491 } else {
1492 if (this.action.equals("setIdentity")) {
1493 setIdentity(this.args.getString(0), this.callbackContext);
1494 } else if (this.action.equals("userCompletedAction")) {
1495 if (this.args.length() == 2) {
1496 userCompletedAction(this.args.getString(0), this.args.getJSONObject(1), this.callbackContext);
1497 } else if (this.args.length() == 1) {
1498 userCompletedAction(this.args.getString(0), this.callbackContext);
1499 }
1500 } else if (this.action.equals("sendCommerceEvent")) {
1501 sendCommerceEvent(this.args.getJSONObject(0), this.args.getJSONObject(1), this.callbackContext);
1502 } else if (this.action.equals("sendBranchEvent")) {
1503 sendBranchEvent(this.args.getString(0), this.args.getJSONObject(1), this.callbackContext);
1504 } else if (this.action.equals("getFirstReferringParams")) {
1505 getFirstReferringParams(this.callbackContext);
1506 } else if (this.action.equals("getLatestReferringParams")) {
1507 getLatestReferringParams(this.callbackContext);
1508 } else if (this.action.equals("logout")) {
1509 logout(this.callbackContext);
1510 } else if (this.action.equals("loadRewards")) {
1511 if (this.args.length() == 1) {
1512 loadRewards(this.args.getString(0), this.callbackContext);
1513 } else {
1514 loadRewards(this.callbackContext);
1515 }
1516 } else if (this.action.equals("redeemRewards")) {
1517 if (this.args.length() == 1) {
1518 redeemRewards(this.args.getInt(0), this.callbackContext);
1519 } else if (this.args.length() == 2) {
1520 redeemRewards(this.args.getInt(0), this.args.getString(1), this.callbackContext);
1521 }
1522 } else if (this.action.equals("getCreditHistory")) {
1523 getCreditHistory(this.callbackContext);
1524 } else if (this.action.equals("createBranchUniversalObject")) {
1525 createBranchUniversalObject(this.args.getJSONObject(0), this.callbackContext);
1526 } else if (this.action.equals("crossPlatformIds")) {
1527 crossPlatformIds(this.callbackContext);
1528 } else if (this.action.equals("lastAttributedTouchData")) {
1529 lastAttributedTouchData(this.callbackContext);
1530 } else if (this.action.equals(("generateShortUrl"))) {
1531 generateShortUrl(this.args.getInt(0), this.args.getJSONObject(1), this.args.getJSONObject(2), this.callbackContext);
1532 } else if (this.action.equals("registerView")) {
1533 registerView(this.args.getInt(0), this.callbackContext);
1534 } else if (this.action.equals("showShareSheet")) {
1535 Object userLocalization = this.args.opt(3);
1536 JSONObject localization = new JSONObject();
1537 //Limitation is that the user must override all the strings
1538 if (userLocalization != null && userLocalization instanceof JSONObject) {
1539 localization = (JSONObject) userLocalization;
1540 } else {
1541 localization.put("shareText", this.args.getString(3) != null ? this.args.getString(3) : "This stuff is awesome: ");
1542 localization.put("shareTitle", "Check this out!");
1543 localization.put("copyToClipboard", "Copy");
1544 localization.put("clipboardSuccess", "Added to clipboard");
1545 localization.put("more", "Show More");
1546 localization.put("shareWith", "Share With");
1547 }
1548 showShareSheet(this.args.getInt(0), this.args.getJSONObject(1), this.args.getJSONObject(2), localization);
1549 }
1550 }
1551 } catch (JSONException e) {
1552 e.printStackTrace();
1553 }
1554 }
1555 }
1556}