Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OneSignal Android NotificationOpenedHandler - start activity

Tags:

java

android

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) 
like image 832
NightMICU Avatar asked Jan 25 '17 23:01

NightMICU


3 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>
like image 187
Gabriel Morin Avatar answered Oct 03 '22 07:10

Gabriel Morin


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);
        }
    }
}
like image 41
NightMICU Avatar answered Oct 03 '22 07:10

NightMICU


Updated code in 2022

OneSignal.NotificationOpenedHandler replaced by OneSignal.OSNotificationOpenedHandler

and result.notification.payload.additionalData replaced by result.notification.additionalData

Full code

class OneSignalNotificationOpenHandler(private val context : Context) : OneSignal.OSNotificationOpenedHandler {
   
   override fun notificationOpened(result: OSNotificationOpenedResult?) {
       if (result == null) return
       val type = result.action.type
       val data = result.notification.additionalData
       
       val name = data.optString("name")
       
       val intent = Intent(context, MainActivity::class.java)
       intent.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_NEW_TASK
       intent.putExtra("name", name)
       context.startActivity(intent)
   }
}

Add it to OneSignel after OneSignal.initWithContext(this)

OneSignal.setNotificationOpenedHandler(OneSignalNotificationOpenHandler(applicationContext))

Don't forget to Add the following to your AndroidManifest.xml to prevent the launching of your main Activity

<application ...>
    <meta-data android:name="com.onesignal.NotificationOpened.DEFAULT" android:value="DISABLE" />
</application>
like image 20
AmrDeveloper Avatar answered Oct 03 '22 05:10

AmrDeveloper