Mengu
Mengu

Reputation: 524

How can I emit event on app launch from notification tap?

i'm using react native for my android app. i have a background service that listens for clipboard events. if something the app is interested in is in clipboard, app sends a push notification to the user. if the app is running on the background, i can emit an event and it's working perfect however if the app is closed and launched by the tap on the notification, nothing is emitted. react context is also empty. how can i emit this event on notification launch?

import android.app.Application;
import android.content.Intent;
import android.view.View;
import android.util.Log;
import android.os.Bundle;
import android.app.NotificationManager;
import android.support.v4.content.LocalBroadcastManager;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import com.facebook.react.bridge.ReactContext;
import com.facebook.react.ReactActivity;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.shell.MainReactPackage;

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "PurchaseButton";
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        onNewIntent(getIntent());
    }

    @Override
    public void onNewIntent(Intent intent) {
        setIntent(intent);
        Bundle bundle = intent.getExtras();

        if (bundle != null) {
            String result = bundle.getString("response");
            int nid = bundle.getInt("nid");
            NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            mNotifyMgr.cancel(nid);

            ReactContext ctx = getReactInstanceManager().getCurrentReactContext();
            if (ctx != null) {
                ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("my.custom.event", result);
                Log.d("PB", "sent broadcast..");
            } else {
                Log.d("PB", "react context is null...");
            }
        }
    }
}

Upvotes: 0

Views: 1587

Answers (1)

Mengu
Mengu

Reputation: 524

in case anyone wonders about this. here's the question answered for react native 0.42.0.

android has activity lifecycles and React Context is not available / instantiated on onCreate and onStart life cycle methods but onResume. we need React Context because this is how we can emit an event to our react native frontend. hence the way to successfully emit events, you must create a handler task, delay it 5 seconds and when it runs, you'll be able to emit the event. it's worth noting that, in my case, if you delay even 1 sec, you get the context however the frontend is not ready to listen for events. here's a sample code:

package com.purchasebutton;

import android.app.Application;
import android.content.Intent;
import android.view.View;
import android.util.Log;
import android.os.Bundle;
import android.os.Handler;
import android.app.NotificationManager;
import android.support.v4.content.LocalBroadcastManager;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import com.facebook.react.bridge.ReactContext;
import com.facebook.react.ReactActivity;
import com.facebook.react.common.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.shell.MainReactPackage;

public class MainActivity extends ReactActivity {

    /**
     * Returns the name of the main component registered from JavaScript.
     * This is used to schedule rendering of the component.
     */
    @Override
    protected String getMainComponentName() {
        return "PurchaseButton";
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        onNewIntent(getIntent());
    }

    @Override
    protected void onResume() {
        super.onResume();
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    ReactContext ctx = getReactInstanceManager().getCurrentReactContext();
                    if (ctx != null) {
                        Intent intent = getIntent();
                        Bundle bundle = intent.getExtras();
                        if (bundle != null) {
                            String result = bundle.getString("response");
                            int nid = bundle.getInt("nid");
                            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                            notificationManager.cancel(nid);
                            ctx.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("product.changed", result);
                        }
                    }
                }
            }, 5000);
    }

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

Upvotes: 1

Related Questions