7

I am trying to get Branch.io to work on Android, but I am running into:

myapplication.MainActivity cannot be cast to android.app.Application

I then changed:

Branch.getAutoInstance(this);

To:

Branch.getInstance();


In onCreate of the Activity.

Then I get:

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean io.branch.referral.Branch.initSession(io.branch.referral.Branch$BranchReferralInitListener, android.net.Uri, android.app.Activity)' on a null object reference
                                                                                   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2416)

Can you help me get the basic up and running?

Following is my AndroidManifest.xml: (note: the branch_key is added in my app code)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.x.myapplication">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <meta-data android:name="io.branch.sdk.BranchKey" android:value="key_live_xxxxxxxxxxxxxxx" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <data android:scheme="yourapp" android:host="open" />
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name="io.branch.referral.InstallListener" android:exported="true">
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER" />
            </intent-filter>
        </receiver>

    </application>

</manifest>


My main Activity:

package com.example.chg.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.content.Intent;
import android.util.Log;

import org.json.JSONObject;

import io.branch.referral.Branch;
import io.branch.referral.BranchError;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Branch.getAutoInstance(this);
        Branch.getInstance();
        setContentView(R.layout.activity_main);
    }

    @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) {
                    // params are the deep linked params associated with the link that the user clicked -> was re-directed to this app
                    // params will be empty if no data found
                    // ... insert custom logic here ...
                } else {
                    Log.i("MyApp", error.getMessage());
                }
            }
        }, this.getIntent().getData(), this);
    }

    @Override
    public void onNewIntent(Intent intent) {
        this.setIntent(intent);
    }
}
Chris G.
  • 23,930
  • 48
  • 177
  • 302

1 Answers1

7

Alex with Branch.io here:

We recently made some changes to our tutorial, and it looks like we missed a few things. I appreciate you posting about this — we'll be pushing an update later today for more clarity.

In this particular case, there are two issues:

  1. A mixup between the Application onCreate() and Activity onCreate() methods, neither of which are actually needed for a basic implementation.
  2. A missing Application class (we accidentally deleted this step from our tutorial completely — my apologies).

To get up and running, update your files as follows:

AndroidManifest.xml

You have three options here:

1. Use the Branch application class (easiest)

If you don't already have a custom application class, this is the simplest approach. Add android:name="io.branch.referral.BranchApp" to your Application class:

Edit: snippet UPDATED per comments below

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.chg.appbranch_01">

    <meta-data android:name="io.branch.sdk.BranchKey" android:value="xxx" />

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:name="io.branch.referral.BranchApp">

        <!--Enable test mode to see debugging data
         (https://dev.branch.io/getting-started/integration-testing/guide/android/#use-debug-mode-to-simulate-fresh-installs)-->
        <meta-data android:name="io.branch.sdk.TestMode" android:value="true" />
        <meta-data android:name="io.branch.sdk.BranchKey" android:value="key_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" />

        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <data android:scheme="theapp" android:host="open" />
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
            </intent-filter>

        </activity>

        <receiver android:name="io.branch.referral.InstallListener" android:exported="true">
            <intent-filter>
                <action android:name="com.android.vending.INSTALL_REFERRER" />
            </intent-filter>
        </receiver>

    </application>

</manifest>

2. Extend your Application class with the BranchApp class

If you already have a custom Application class, this is the simplest approach. Your AndroidManifext.xml file will look like this:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:name="com.your.app.CustomApplicationClass" >

Your custom Application class (CustomApplicationClass in the example above) will look like this:

public final class CustomApplicationClass extends YourApp {
    @Override
    public void onCreate() {
        super.onCreate();
    }
}

3. Integrate directly into your custom application class

The most custom approach, for advanced implementations. You'd have your AndroidManifext.xml file set up the same as above:

<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:name="com.your.app.CustomApplicationClass" >

And then configure your Application class as follows:

public final class CustomApplicationClass {
    @Override
    public void onCreate() {
        super.onCreate();
        Branch.getAutoInstance(this);
    }
}

Activity Definition

Remove the onCreate() calls. They aren't needed here and are actually the cause of your error message (Branch.getAutoInstance(this) was passing the Activity context as this, when the SDK was expecting the Application context from option 3 above).

import io.branch.referral.Branch;
import io.branch.referral.BranchError;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @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) {
                    // params are the deep linked params associated with the link that the user clicked -> was re-directed to this app
                    // params will be empty if no data found
                    // ... insert custom logic here ...
                } else {
                    Log.i("MyApp", error.getMessage());
                }
            }
        }, this.getIntent().getData(), this);
    }

    @Override
    public void onNewIntent(Intent intent) {
        this.setIntent(intent);
    }
}

Sorry for the inconvenience!

Alex Bauer
  • 13,147
  • 1
  • 27
  • 44
  • 1
    Hi Alex. I am sorry, but I can not get it to work. Will it be possible for you to create a project from the tutoria(SDK Integration Guide)l and place it on github? – Chris G. May 30 '16 at 08:15
  • @ChrisG. take a look at the [Android testbed app](https://github.com/BranchMetrics/android-branch-deep-linking/tree/master/Branch-SDK-TestBed)! That uses option 2 as described above. – Alex Bauer May 30 '16 at 08:20
  • Hi Alex. Did you look at this? Thanks in advance. – Chris G. Jun 01 '16 at 11:52
  • Hi @ChrisG., I took a look at this. As far as I can tell, this skeleton app doesn't completely follow the current SDK integration guide instructions, and also didn't implement any of the three approaches described in my answer above. I was able to get things to compile fairly easily by using **Option 1**, but it looks like I can't push those changes directly to that repo so I have updated my answer to include exactly the code I used. Let me know if that helps! – Alex Bauer Jun 02 '16 at 05:31
  • Hi Alex I have added you to the github project as collaborator: https://github.com/JCzz/AppBranch_01/invitations. – Chris G. Jun 02 '16 at 12:33
  • Do you know if I have to uninstall the app each time I run. I have added the following: From the Run menu -> Edit Configurations... -> Before Launch -> Add Gradle-aware Make -> ":app:uninstallAll" without the "" – Chris G. Jun 02 '16 at 12:34
  • Just to be clear: I am testing this by 1. running the url in Android browser - this gives "Webpage not available". 2. Starting the app in Android Studio. – Chris G. Jun 02 '16 at 12:36
  • Hey @ChrisG., I just pushed up the changes on GitHub. You shouldn't have to uninstall the app each time. There were two other small changes: URL schemes should be all lowercase, and Branch actually needs a default fallback URL set in the dashboard before it opens the app, so make sure you have one of those set first :). – Alex Bauer Jun 02 '16 at 23:41
  • Fantastic! Great to hear. Good luck! – Alex Bauer Jun 03 '16 at 13:32
  • @AlexBauer what is the reason to override onNewIntent? How would captured intent be used and when? From what I can see activity's intent is used only in onStart but it won't be called after onNewIntent. – Mikhail Sep 14 '17 at 15:57
  • @Mikhail great question! Branch always recommends using `singleTask` mode (multiple instances of an activity when handing deep links is a headache), so overriding `onNewIntent` allows us to grab link data if the activity is already running. – Alex Bauer Sep 14 '17 at 17:57
  • @AlexBauer to grab link data and do something it is not enough just to assign intent. Do you intercept activity's onResume via ActivityLifecycleCallbacks to process captured intent or what? – Mikhail Sep 15 '17 at 03:24
  • @AlexBauer another thing I've noticed is that session callback is called every time activity goes background/foreground if "Don't keep activities" flag is set. What even worse is that data obtained in the callback on this occasion differs from the original one. I've opened support case with Branch and even provided sample application to illustrate the issue I'm having. – Mikhail Sep 15 '17 at 15:01
  • @Mikhail based on what I understand of how the SDK works, that sounds like the expected behavior. Hopefully our Integrations team will have a more complete answer for you soon! – Alex Bauer Sep 15 '17 at 15:05
  • Hi @AlexBauer, i want to ask, in the tutorial said that : "Note that, in this case, if the app is opened organically, Branch will auto-initialize behind the scenes and calling sessionBuilder()…init() will return an error. This is because the SDK will already be initialized.", i keep getting this error, how to check if the session is already initialized ?, so i dont't need to call the session builder ini. Thank you. – Bhimbim Apr 08 '20 at 17:11