Home » Android » java – OneSignal Android NotificationOpenedHandler – start activity

java – OneSignal Android NotificationOpenedHandler – start activity

Posted by: admin June 15, 2020 Leave a comment

Questions:

Trying to migrate from Parse to OneSignal and I am stuck on how to start a new Activity after the user clicks on a push notification. My handler is working, the log shows the text, the issue seems to be how to gain access to the application context from within my push opened handler. The example code is vague, getApplicationContext() does not work without first doing something else.

One post I came upon, unrelated to OneSignal, suggests extending the Application class to gain access to the application context. This did not produce any syntax errors but my app crashes.

Code:

package com.linkedresponder.onesignal;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;

import com.onesignal.OSNotificationAction;
import com.onesignal.OSNotificationOpenResult;
import com.onesignal.OneSignal;

import org.json.JSONObject;

class NotificationOpenHandler extends Application implements OneSignal.NotificationOpenedHandler {
    // This fires when a notification is opened by tapping on it.
    private Context mContext;
    @Override
    public void onCreate() {
        this.mContext = getApplicationContext();
    }
    @Override
    public void notificationOpened(OSNotificationOpenResult result) {
        OSNotificationAction.ActionType actionType = result.action.type;
        JSONObject data = result.notification.payload.additionalData;
        String customKey;

        if (data != null) {
            customKey = data.optString("customkey", null);
            if (customKey != null) {
                Log.i("OneSignalExample", "customkey set with value: " + customKey);
            } else {
                Log.i("OneSignalExample", "No data");
            }
        }

        if (actionType == OSNotificationAction.ActionType.ActionTaken)
            Log.i("OneSignalExample", "Button pressed with id: " + result.action.actionID);

        Intent intent = new Intent(mContext, PushClicked.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
         startActivity(intent);
    }
}

Error:

er.onesignal E/AndroidRuntime: FATAL EXCEPTION: main Process: com.linkedresponder.onesignal, PID: 5680
   java.lang.RuntimeException: Unable to start receiver com.onesignal.NotificationOpenedReceiver: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
   at android.app.ActivityThread.handleReceiver(ActivityThread.java:3018)
   at android.app.ActivityThread.-wrap18(ActivityThread.java)
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1544)
   at android.os.Handler.dispatchMessage(Handler.java:102)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6077)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
   at android.content.ComponentName.<init>(ComponentName.java:128)
   at android.content.Intent.<init>(Intent.java:4868)
   at com.linkedresponder.onesignal.NotificationOpenHandler.notificationOpened(NotificationOpenHandler.java:41)
   at com.onesignal.OneSignal.fireNotificationOpenedHandler(OneSignal.java:1009)
   at com.onesignal.OneSignal.runNotificationOpenedCallback(OneSignal.java:954)
   at com.onesignal.OneSignal.handleNotificationOpen(OneSignal.java:1041)
   at com.onesignal.NotificationOpenedProcessor.processIntent(NotificationOpenedProcessor.java:101)
   at com.onesignal.NotificationOpenedProcessor.processFromActivity(NotificationOpenedProcessor.java:57)
   at com.onesignal.NotificationOpenedReceiver.onReceive(NotificationOpenedReceiver.java:11)
   at android.app.ActivityThread.handleReceiver(ActivityThread.java:3011)
   at android.app.ActivityThread.-wrap18(ActivityThread.java) 
   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1544) 
   at android.os.Handler.dispatchMessage(Handler.java:102) 
   at android.os.Looper.loop(Looper.java:154) 
   at android.app.ActivityThread.main(ActivityThread.java:6077) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 
How to&Answers:

Here’s how I made it work:

public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        OneSignal.startInit(this)
                .setNotificationOpenedHandler(new MyNotificationOpenedHandler(this))
                .init();
    }
}

The NotificationOpenedHandler custom class

public class MyNotificationOpenedHandler implements OneSignal.NotificationOpenedHandler {

    private Application application;

    public MyNotificationOpenedHandler(Application application) {
        this.application = application;
    }

    @Override
    public void notificationOpened(OSNotificationOpenResult result) {

        // Get custom datas from notification
        JSONObject data = result.notification.payload.additionalData;
        if (data != null) {
            String myCustomData = data.optString("key", null);
        }

        // React to button pressed
        OSNotificationAction.ActionType actionType = result.action.type;
        if (actionType == OSNotificationAction.ActionType.ActionTaken)
            Log.i("OneSignalExample", "Button pressed with id: " + result.action.actionID);

        // Launch new activity using Application object
        startApp();
    }

    private void startApp() {
        Intent intent = new Intent(application, MyActivity.class)
                .setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
        application.startActivity(intent);
    }
}

Don’t forget to add this to your manifest:

<application ...>
   <meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="DISABLE" />
</application>

Answer:

The short answer to this issue is to include your handler for the push notification open within the same class where you initialize OneSignal:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Init OneSignal
        OneSignal.startInit(this).setNotificationOpenedHandler(new NotificationOpenHandler()).init();

        Toolbar mToolbar = (Toolbar) findViewById(R.id.app_bar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayUseLogoEnabled(true);
        getSupportActionBar().setLogo(R.drawable.ic_launcher);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .add(R.id.container, new RecordingsFragment())
                    .commit();
        }
    }

    class NotificationOpenHandler implements OneSignal.NotificationOpenedHandler {
        // This fires when a notification is opened by tapping on it.
        @Override
        public void notificationOpened(OSNotificationOpenResult result) {
            OSNotificationAction.ActionType actionType = result.action.type;
            JSONObject data = result.notification.payload.additionalData;

            String stationName = data.optString("stationName");
            String timestamp = data.optString("timestamp");
            String filename = data.optString("filename");
            String url = getString(R.string.callResourceUrl) + filename;

            Intent intent = new Intent(getApplicationContext(), CallActivity.class);
            intent.putExtra("stationName", stationName);
            intent.putExtra("time", timestamp);
            intent.putExtra("url", url);
//            intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
    }
}