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.
Related
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
I’m using the code given here.
I put those code blocks as classes in my project’s util package. And then in the main activity class I wrote this..
class MenuActivity {
// Variable declaration
private final CompositeSubscription mConnectionSubscription = new CompositeSubscription();
#Override
protected void onCreate(Bundle savedInstanceState) {
// Some initialisation of UI elements done here
mConnectionSubscription.add(AppObservable.bindActivity(this, NetworkUtils.observe(this)).subscribe(new Action1<NetworkUtils.State>() {
#Override
public void call(NetworkUtils.State state) {
if(state == NetworkUtils.State.NOT_CONNECTED)
Timber.i("Connection lost");
else
Timber.i("Connected");
}
}));
}
My goal is to monitor the changes and change a variable MyApp.isConnected defined in the MyApp class statically whenever the network changes to true false. Help would be appreciated. Thank you 😄
You asked me for an answer in another thread. I'm answering late, because I needed some time to develop and test solution, which I find good enough.
I've recently created new project called ReactiveNetwork.
It's open-source and available at: https://github.com/pwittchen/ReactiveNetwork.
You can add the following dependency to your build.gradle file:
dependencies {
compile 'com.github.pwittchen:reactivenetwork:x.y.z'
}
Then, you can replace x.y.z with the latest version number.
After that, you can use library in the following way:
ReactiveNetwork.observeNetworkConnectivity(context)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<ConnectivityStatus>() {
#Override public void call(Connectivity connectivity) {
if(connectivity.getState() == NetworkInfo.State.DISCONNECTED) {
Timber.i("Connection lost");
} else if(connectivity.getState() == NetworkInfo.State.CONNECTED) {
Timber.i("Connected");
}
}
});
You can also use filter(...) method from RxJava if you want to react only on a single type of event.
You can create a subscription in onResume() method and then unsubscribe it in onPause() method inside Activity.
You can find more examples of usage and sample app on the website of the project on GitHub.
Moreover, you can read about NetworkInfo.State enum from Android API, which is now used by the library.
Try to use rxnetwork-android:
public class MainActivity extends AppCompatActivity{
private Subscription sendStateSubscription;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Observable<RxNetwork.State> sendStateStream =
RxNetwork.stream(this);
sendStateSubscription = AppObservable.bindActivity(
this, sendStateStream
).subscribe(new Action1<RxNetwork.State>() {
#Override public void call(RxNetwork.State state) {
if(state == RxNetwork.State.NOT_CONNECTED)
Timber.i("Connection lost");
else
Timber.i("Connected");
}
});
}
#Override protected void onDestroy() {
sendStateSubscription.unsubscribe();
sendStateSubscription = null;
super.onDestroy();
}
}
I've got a Andriod Studio project and I'm trying to use the SocketIOClient from the AndroidAsync library. I'm building the library with the command:
dependencies {
compile 'com.koushikdutta.androidasync:AndroidAsync:1.0.0'
}
I was able to get the websocket example to work, but there's seems to be a version issue with the 1.0 and the SocketIOClient example. I've also tried using the 2.0 jar file, but SocketIOClient doesn't appear to be defined there at all(this is one of my first andriod applications, so maybe I'm just doing something wrong). Does anyone know what needs to be done to get the following code to compile:
SocketIOClient.connect(AsyncHttpClient.getDefaultInstance(), "http://192.168.1.2:3000", new ConnectCallback() {
#Override
public void onConnectCompleted(Exception ex, SocketIOClient client) {
if (ex != null) {
ex.printStackTrace();
return;
}
client.setStringCallback(new StringCallback() {
#Override
public void onString(String string) {
System.out.println(string);
}
});
client.on("someEvent", new EventCallback() {
#Override
public void onEvent(JSONArray argument, Acknowledge acknowledge) {
System.out.println("args: " + arguments.toString());
}
});
client.setJSONCallback(new JSONCallback() {
#Override
public void onJSON(JSONObject json) {
System.out.println("json: " + json.toString());
}
});
}
});
Thanks,
Scott
I am using Codenameone and ZXing to read a QRCode. When I call the Scanner, my mobile opens the QRCode reader application and I get to read the QRCode except that when android takes me back to my app it goes through init then start statuses. Which moves me back to the login form of my application instead of continuing filling the form that I was in.
Any help on what to do to stay in the same form? Is there something I'm doing wrong? Thanks in advance.
EverproX.addMessage("Before Scan\n");
CodeScanner.getInstance().scanQRCode(new ScanResult() {
public void scanCompleted(String contents, String formatName, byte[] rawBytes) {
EverproX.addMessage("Scan Completed "+contents);
}
public void scanCanceled() {
EverproX.addMessage("Scan Cancelled");
}
public void scanError(int errorCode, String message) {
EverproX.addMessage("Scan Error "+errorCode+" "+message);
}
});
EverproX can be seen as a log class.
By analyzing our log we can say that as soon as we call the CodeScanner.getInstance().scanQRCode() the application is called for 'Destroy'. Then after the scanning is done it goes again through the init and start. It never goes into the scanComplete scanCanceled or scanError Callbacks.
Is it normal that the App is destroyed upon call of CodeScanner? Many thanks.
Inside your codenameone project, you should find a class named (for example MyApp.java) based on your app's name, modify the code to read something like similar to this:
public class MyApp {
private Form current;
public void init(Object context) {
// Pro users - uncomment this code to get crash reports sent to you automatically
Display.getInstance().addEdtErrorHandler(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
evt.consume();
Log.p("Exception in AppName version " + Display.getInstance().getProperty("AppVersion", "Unknown"));
Log.p("OS " + Display.getInstance().getPlatformName());
Log.p("Error " + evt.getSource());
Log.p("Current Form " + Display.getInstance().getCurrent().getName());
Log.e((Throwable) evt.getSource());
Log.sendLog();
}
});
}
public void start() {
if (current != null) {
current.show();
return;
}
new StateMachine("/theme");
}
public void stop() {
current = Display.getInstance().getCurrent();
}
public void destroy() {
current = null;
}
}
I'm using 'Retrofit' for making asynchronous network requests, how might i right a function for handling logins? For instance i've currently attempted:
public UserAuthResponse Login(String username, String password) {
try {
Callback<UserAuthResponse> getAuthCallback = new Callback<UserAuthResponse>() {
#Override
public void failure(RetrofitError arg0) {
if (arg0 != null) {
if (arg0.getMessage() != null
&& arg0.getMessage().length() > 0) {
Log.e("KFF-Retrofit", arg0.getMessage());
}
}
}
#Override
public void success(UserAuthResponse listItem,
retrofit.client.Response arg1) {
Log.e("dg", listItem.getUser().getFirstname());
}
};
service.authUser(username, MD5(password), getAuthCallback);
return response;
} catch (RetrofitError e) {
e.printStackTrace();
return null;
}
}
But this is flawed: there is no way of returning the 'UserAuthResponse' from the function? How can i pass back the result?
It seems like i need a synchronous call to the web service but then i'm hit with a 'NetworkOnMainThreadException'
What is the best practice for things like this? Sorry about the poor explanation, struggling to form the right words.
Well the things is that when you're using the Callback as your means of getting the results from Retrofit you automatically giving away the possibility of having the response returned inline. There's a few ways this can be solved. I suppose it's up to you to choose which one fits best with your design.
You could decide to not use the Callback approach and use the inline result from Retrofit but then you'd need to handle the scheduling yourself otherwise you'll hit the Exception of NetworkOnMainThreadException like you mentioned.
You could also pass in a listener to your login method. This listener could then be called by the result Callback. This could be useful if you're trying to hide Retrofit behind some sort of service layer and expose a simple login interface.
interface OnLoginListener {
onLoginSuccessful(UserAuthResponse response);
onLoginFailed(Throwable t);
}
public void Login(String username, String password, final OnLoginListener listener) {
Callback<UserAuthResponse> getAuthCallback = new Callback<UserAuthResponse>() {
#Override
public void failure(RetrofitError e) {
// You can handle Retrofit exception or simply pass them down to the listener as is
listener.onLoginFailed(e);
}
#Override
public void success(UserAuthResponse listItem,
retrofit.client.Response arg1) {
// handle successful case here and pass down the data to the listener
listener.onLoginSucessful(listItem);
}
};
service.authUser(username, MD5(password), getAuthCallback);
}
use this line i Manifest
<uses-permission android:name="android.permission.INTERNET"/>
or use this before network operation (not suggestible)
if (Build.VERSION.SDK_INT>= 10) {
ThreadPolicy tp = ThreadPolicy.LAX;
StrictMode.setThreadPolicy(tp);
}