Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to read from field 'com.twilivoicreatenative.jsEventEmitter com.twiliovoicereactnative.Voice application OnProxy.jsEventEmitter on a null object reference' #426

Open
nayagam-ibz opened this issue Sep 18, 2024 · 2 comments
Labels
needs more info Needs more info from the issue author.

Comments

@nayagam-ibz
Copy link

No description provided.

@mhuynh5757
Copy link
Collaborator

Hi @nayagam-ibz please fill out the issue template when filing issues in this repository. The info in the template is necessary for us to help debug your issue.

@mhuynh5757 mhuynh5757 added the needs more info Needs more info from the issue author. label Oct 3, 2024
@ayazalphasquad
Copy link

Hi @mhuynh5757 ,

I need help configuring this package with the android updated SDK API level 34. I followed all the steps outlined in the reference application, but I'm unable to run the app. It crashes every time we try to open it.

If we don't configure the application then I get the below error:

----- Error Start------
Attempt to read from field 'come.twiliovoicereactnative.JSEventEmitter com.twiliovoicereactnative.VoiceApplicationProxy.JSEventEmiiter" on a null object reference in the method com.twiliovoicereactnative.JSEventEmittercom.twiliovoicereactnative.VoiceApplicationProxy.get.JSEventEmitter()
-----Error End-------

I've used the same JNI libraries from the reference application and configured them in the build.gradle file, but it hasn't resolved the issue.

Here is the code:

Files paths:
android/app/src/main/java/com/sigmago/MainActivity.java
android/app/src/main/java/com/sigmago/MainApplication.java
android/app/src/main/java/com/sigmago/MainReactNativeHost.java
android/app/src/main/java/com/sigmago/newarchitecture/MainApplicationReactNativeHost.java
android/app/src/main/java/com/sigmago/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java
android/app/src/main/java/com/sigmago/newarchitecture/components/MainComponentsRegistry.java
android/app/src/main/java/com/sigmago/jni/CMakeLists.txt

- MainActivity.java:

package com.sigmago;

import android.Manifest;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.widget.Toast;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactActivityDelegate;
import com.twiliovoicereactnative.VoiceActivityProxy;

public class MainActivity extends ReactActivity {

public static class MainActivityDelegate extends ReactActivityDelegate {
public MainActivityDelegate(ReactActivity activity, String mainComponentName) {
super(activity, mainComponentName);
}

@Override
protected ReactRootView createRootView() {
  ReactRootView reactRootView = new ReactRootView(getContext());
  // If you opted-in for the New Architecture, we enable the Fabric Renderer.
  reactRootView.setIsFabric(BuildConfig.IS_NEW_ARCHITECTURE_ENABLED);
  return reactRootView;
}

@Override
protected boolean isConcurrentRootEnabled() {
  // If you opted-in for the New Architecture, we enable Concurrent Root (i.e. React 18).
  // More on this on https://reactjs.org/blog/2022/03/29/react-v18.html
  return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
}

}

private final VoiceActivityProxy activityProxy = new VoiceActivityProxy(
this,
permission -> {
if (Manifest.permission.RECORD_AUDIO.equals(permission)) {
Toast.makeText(
MainActivity.this,
"Microphone permissions needed. Please allow in your application settings.",
Toast.LENGTH_LONG).show();
} else if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) &&
Manifest.permission.BLUETOOTH_CONNECT.equals(permission)) {
Toast.makeText(
MainActivity.this,
"Bluetooth permissions needed. Please allow in your application settings.",
Toast.LENGTH_LONG).show();
} else if ((Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) &&
Manifest.permission.POST_NOTIFICATIONS.equals(permission)) {
Toast.makeText(
MainActivity.this,
"Notification permissions needed. Please allow in your application settings.",
Toast.LENGTH_LONG).show();
}
});

/**

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

/**

  • Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
  • DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
  • (aka React 18) with two boolean flags.
    */
    @OverRide
    protected ReactActivityDelegate createReactActivityDelegate() {
    return new DefaultReactActivityDelegate(
    this,
    getMainComponentName(),
    // If you opted-in for the New Architecture, we enable the Fabric Renderer.
    DefaultNewArchitectureEntryPoint.getFabricEnabled(), // fabricEnabled
    // If you opted-in for the New Architecture, we enable Concurrent React (i.e. React 18).
    DefaultNewArchitectureEntryPoint.getConcurrentReactEnabled() // concurrentRootEnabled
    );
    }

@OverRide
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityProxy.onCreate(savedInstanceState);
}

@OverRide
public void onDestroy() {
activityProxy.onDestroy();
super.onDestroy();
}

@OverRide
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
activityProxy.onNewIntent(intent);
}
}

  • MainApplication.java:

package com.sigmago;

import android.app.Application;

import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import java.util.List;

import com.sigmago.newarchitecture.MainApplicationReactNativeHost;
import com.twiliovoicereactnative.VoiceApplicationProxy;
import com.twiliovoicereactnative.VoiceApplicationProxy.VoiceReactNativeHost;

import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import org.jetbrains.annotations.Nullable;
import android.content.Context;

public class MainApplication extends Application implements ReactApplication {

private final MainApplicationReactNativeHost mNewArchitectureNativeHost =
        new MainApplicationReactNativeHost(this);

private final VoiceApplicationProxy voiceApplicationProxy;

// Use VoiceReactNativeHost instead of ReactNativeHost
private final VoiceReactNativeHost mVoiceReactNativeHost = 
    new VoiceReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            @SuppressWarnings("UnnecessaryLocalVariable")
            List<ReactPackage> packages = new PackageList(this).getPackages();
            // Add any packages here if needed
            return packages;
        }

        @Override
        protected String getJSMainModuleName() {
            return "index";
        }

    };

public MainApplication() {
    voiceApplicationProxy = new VoiceApplicationProxy(mVoiceReactNativeHost);
}

@Override
public ReactNativeHost getReactNativeHost() {
    return mVoiceReactNativeHost; // Use the VoiceReactNativeHost
}

@Override
public Intent registerReceiver(@Nullable BroadcastReceiver receiver, IntentFilter filter) {
    if (Build.VERSION.SDK_INT >= 34 && getApplicationInfo().targetSdkVersion >= 34) {
        return super.registerReceiver(receiver, filter, Context.RECEIVER_EXPORTED);
    } else {
        return super.registerReceiver(receiver, filter);
    }
}

@Override
public void onCreate() {
    super.onCreate();
    voiceApplicationProxy.onCreate(); 
    SoLoader.init(this, /* native exopackage */ false);
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
        DefaultNewArchitectureEntryPoint.load();
    }
    com.sigmago.ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}

@Override
public void onTerminate() {
    voiceApplicationProxy.onTerminate(); 
    super.onTerminate();
}

}

- MainReactNativeHost.java:

package com.sigmago;

import android.app.Application;
import com.facebook.react.PackageList;
import com.facebook.react.ReactPackage;
import com.twiliovoicereactnative.VoiceApplicationProxy;
import java.util.List;

class MainReactNativeHost extends VoiceApplicationProxy.VoiceReactNativeHost {
public MainReactNativeHost(Application application) {
super(application);
}

@Override
public boolean getUseDeveloperSupport() {
    return BuildConfig.DEBUG;
}

@Override
protected List<ReactPackage> getPackages() {
    List<ReactPackage> packages = new PackageList(this).getPackages();
    // Packages that cannot be autolinked yet can be added manually here
    // packages.add(new MyReactNativePackage());
    return packages;
}

@Override
protected String getJSMainModuleName() {
    return "index";
}

}

  • MainComponentsRegistry.java:

package com.sigmago.newarchitecture.components;

import com.facebook.jni.HybridData;
import com.facebook.proguard.annotations.DoNotStrip;
import com.facebook.react.fabric.ComponentFactory;
import com.facebook.soloader.SoLoader;

/**

  • Class responsible to load the custom Fabric Components. This class has native methods and needs a
  • corresponding C++ implementation/header file to work correctly (already placed inside the jni/
  • folder for you).
  • Please note that this class is used ONLY if you opt-in for the New Architecture (see the

  • newArchEnabled property). Is ignored otherwise.
    */
    @DoNotStrip
    public class MainComponentsRegistry {
    static {
    SoLoader.loadLibrary("fabricjni");
    }

@DoNotStrip private final HybridData mHybridData;

@DoNotStrip
private native HybridData initHybrid(ComponentFactory componentFactory);

@DoNotStrip
private MainComponentsRegistry(ComponentFactory componentFactory) {
mHybridData = initHybrid(componentFactory);
}

@DoNotStrip
public static MainComponentsRegistry register(ComponentFactory componentFactory) {
return new MainComponentsRegistry(componentFactory);
}
}

- MainApplicationTurboModuleManagerDelegate.java:

package com.sigmago.newarchitecture.modules;

import com.facebook.jni.HybridData;
import com.facebook.react.ReactPackage;
import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.soloader.SoLoader;
import java.util.List;

/**

  • Class responsible to load the TurboModules. This class has native methods and needs a
  • corresponding C++ implementation/header file to work correctly (already placed inside the jni/
  • folder for you).
  • Please note that this class is used ONLY if you opt-in for the New Architecture (see the

  • newArchEnabled property). Is ignored otherwise.
    */
    public class MainApplicationTurboModuleManagerDelegate
    extends ReactPackageTurboModuleManagerDelegate {

private static volatile boolean sIsSoLibraryLoaded;

protected MainApplicationTurboModuleManagerDelegate(
ReactApplicationContext reactApplicationContext, List packages) {
super(reactApplicationContext, packages);
}

protected native HybridData initHybrid();

native boolean canCreateTurboModule(String moduleName);

public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
protected MainApplicationTurboModuleManagerDelegate build(
ReactApplicationContext context, List packages) {
return new MainApplicationTurboModuleManagerDelegate(context, packages);
}
}

@OverRide
protected synchronized void maybeLoadOtherSoLibraries() {
if (!sIsSoLibraryLoaded) {
// If you change the name of your application .so file in the Android.mk file,
// make sure you update the name here as well.
SoLoader.loadLibrary("sigmago_appmodules"); // Updated library name according to the package name
sIsSoLibraryLoaded = true;
}
}
}

  • CMakeLists.txt

cmake_minimum_required(VERSION 3.13)

Define the library name here.

project(sigmago_appmodules)

This file includes all the necessary to let you build your application with the New Architecture.

include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)

  • Android/app/build.gradle:

Added the below condition after defaultConfig:

if (isNewArchitectureEnabled()) {
// We configure the NDK build only if you decide to opt-in for the New Architecture.
externalNativeBuild {
cmake {
path "$projectDir/src/main/jni/CMakeLists.txt"
}
}
def reactAndroidProjectDir = project(':ReactAndroid').projectDir
def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
into("$buildDir/react-ndk/exported")
}
def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
into("$buildDir/react-ndk/exported")
}
afterEvaluate {
// If you wish to add a custom TurboModule or component locally,
// you should uncomment this line.
// preBuild.dependsOn("generateCodegenArtifactsFromSchema")
preDebugBuild.dependsOn(packageReactNdkDebugLibs)
preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)

        // Due to a bug inside AGP, we have to explicitly set a dependency
        // between configureCMakeDebug* tasks and the preBuild tasks.
        // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
        configureCMakeRelWithDebInfo.dependsOn(preReleaseBuild)
        configureCMakeDebug.dependsOn(preDebugBuild)
        reactNativeArchitectures().each { architecture ->
            tasks.findByName("configureCMakeDebug[${architecture}]")?.configure {
                dependsOn("preDebugBuild")
            }
            tasks.findByName("configureCMakeRelWithDebInfo[${architecture}]")?.configure {
                dependsOn("preReleaseBuild")
            }
        }
    }
  • Android/build.gradle:

    buildToolsVersion = "34.0.0"
    minSdkVersion = 23
    compileSdkVersion = 34
    targetSdkVersion = 34

      // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
      ndkVersion = "23.1.7779620"
    

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs more info Needs more info from the issue author.
Projects
None yet
Development

No branches or pull requests

3 participants