Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I tie a custom lifecycle listener in expo native modules into my main module?

I've added a native view which requires me to ask the user for some permissions and I want to do this in the onCreate method. After reading over expos documentation I came across some boilerplate code to do this. So I added:

class MyLibPackage : Package {
  override fun createReactActivityLifecycleListeners(activityContext: Context): List<ReactActivityLifecycleListener> {
    return listOf(MyLibReactActivityLifecycleListener())
  }
}

and created the following class:

class MyLibReactActivityLifecycleListener : ReactActivityLifecycleListener {
    private var requestPermissionLauncher: ActivityResultLauncher<String>? = null

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    override fun onCreate(activity: Activity, savedInstanceState: Bundle?) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            handleNotificationPermission(activity)
        }
    }

    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private fun handleNotificationPermission(activity: Activity) {
        if (activity is androidx.activity.ComponentActivity) {
            requestPermissionLauncher = activity.registerForActivityResult(
                ActivityResultContracts.RequestPermission()
            ) { isGranted: Boolean ->
                if (isGranted) {
                    // Permission granted
                } else {
                    // Permission denied
                    // Provide user feedback
                }
            }
        }
        handleNotificationPermission(activity)

        when {
            ContextCompat.checkSelfPermission(
                activity,
                Manifest.permission.POST_NOTIFICATIONS
            ) == PackageManager.PERMISSION_GRANTED -> {
                // Permission already granted
            }
            ActivityCompat.shouldShowRequestPermissionRationale(
                activity, Manifest.permission.POST_NOTIFICATIONS) -> {
                // Provide rationale to the user
                // For example, show a dialog explaining why the permission is needed
            }
            else -> {
                // Request permission
                requestPermissionLauncher?.launch(Manifest.permission.POST_NOTIFICATIONS)
            }
        }
    }
}

In this code the MyLibPackage never actually runs and I'm not sure how to integrate it with the view.

My full Module file looks like this with NativeAudioViewModule being the view i'm creating.

package expo.modules.nativeaudioview

import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
import expo.modules.core.interfaces.Package
import expo.modules.core.interfaces.ReactActivityLifecycleListener
import android.content.Context


class MyLibPackage : Package {
  override fun createReactActivityLifecycleListeners(activityContext: Context): List<ReactActivityLifecycleListener> {
    return listOf(MyLibReactActivityLifecycleListener())
  }
}

class NativeAudioViewModule : Module() {
  override fun definition() = ModuleDefinition {
    Name("NativeAudioView")

    View(NativeAudioView::class) {
      Events("onStatusChange")
      Prop("url") { view: NativeAudioView, url: String? ->
        if (url != null) {
          view.url = url
        }
      }
      Prop("title") { view: NativeAudioView, title: String? ->
        if (title != null) {
          view.title = title
        }
      }
    }
  }
}
like image 540
KAT Avatar asked Oct 19 '25 11:10

KAT


1 Answers

I just spent an hour and a half figuring out the same problem.

In theory, your package class is picked up automatically by the expo-modules-autolinking package and referenced in a Java file that is generated. Note that this is dependent on the filename ending in Package.kt or Package.java. The generated file is in node_modules/expo/android/build/generated/expo/src/main/java/expo/modules/ExpoModulesPackageList.java.

However there is a caching issue and gradle doesn't know it needs to regenerate that file once you've added the Package class. I couldn't find a clean way to trigger the gradle task specifically, so I simply deleted the android build cache: rm -rf node_modules/expo/android/build/. With the next rebuild the file is regenerated and correctly references the Package class.

like image 148
s-ol Avatar answered Oct 22 '25 00:10

s-ol



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!