@@ -375,6 +375,43 @@ class MediaButtonPackage : ReactPackage {
375375}
376376` ;
377377
378+ /**
379+ * Resolves the Android namespace/package name from build.gradle or build.gradle.kts.
380+ * Probes both Groovy and Kotlin DSL files and uses a regex that handles both syntaxes:
381+ * - Groovy: namespace 'com.example.app' or namespace "com.example.app"
382+ * - Kotlin DSL: namespace = "com.example.app"
383+ *
384+ * @param {string } projectRoot - The project root directory
385+ * @param {string } fallback - Fallback package name if not found (default: 'com.resgrid.unit')
386+ * @returns {string } The resolved namespace or fallback
387+ */
388+ function resolveBasePackageName ( projectRoot , fallback = 'com.resgrid.unit' ) {
389+ // Regex that accepts optional equals sign for both Groovy and Kotlin DSL
390+ const namespaceRegex = / n a m e s p a c e \s * (?: = ) ? \s * [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / ;
391+
392+ // Probe build.gradle (Groovy DSL) first
393+ const groovyPath = path . join ( projectRoot , 'android' , 'app' , 'build.gradle' ) ;
394+ if ( fs . existsSync ( groovyPath ) ) {
395+ const content = fs . readFileSync ( groovyPath , 'utf-8' ) ;
396+ const match = content . match ( namespaceRegex ) ;
397+ if ( match ) {
398+ return match [ 1 ] ;
399+ }
400+ }
401+
402+ // Probe build.gradle.kts (Kotlin DSL) as fallback
403+ const ktsPath = path . join ( projectRoot , 'android' , 'app' , 'build.gradle.kts' ) ;
404+ if ( fs . existsSync ( ktsPath ) ) {
405+ const content = fs . readFileSync ( ktsPath , 'utf-8' ) ;
406+ const match = content . match ( namespaceRegex ) ;
407+ if ( match ) {
408+ return match [ 1 ] ;
409+ }
410+ }
411+
412+ return fallback ;
413+ }
414+
378415/**
379416 * Expo config plugin to add MediaButtonModule for AirPods/earbuds PTT support.
380417 *
@@ -439,17 +476,8 @@ const withMediaButtonModule = (config) => {
439476 async ( config ) => {
440477 const projectRoot = config . modRequest . projectRoot ;
441478
442- // Read the package name from the Android manifest or build.gradle
443- const buildGradlePath = path . join ( projectRoot , 'android' , 'app' , 'build.gradle' ) ;
444- let packageName = 'com.resgrid.unit' ; // Default fallback
445-
446- if ( fs . existsSync ( buildGradlePath ) ) {
447- const buildGradleContent = fs . readFileSync ( buildGradlePath , 'utf-8' ) ;
448- const namespaceMatch = buildGradleContent . match ( / n a m e s p a c e \s + [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / ) ;
449- if ( namespaceMatch ) {
450- packageName = namespaceMatch [ 1 ] ;
451- }
452- }
479+ // Resolve the package name from build.gradle or build.gradle.kts
480+ const packageName = resolveBasePackageName ( projectRoot ) ;
453481
454482 const packagePath = packageName . replace ( / \. / g, '/' ) ;
455483 const androidSrcPath = path . join ( projectRoot , 'android' , 'app' , 'src' , 'main' , 'java' , packagePath ) ;
@@ -482,18 +510,9 @@ const withMediaButtonModule = (config) => {
482510
483511 // Check if MediaButtonPackage is already imported/added
484512 if ( ! mainApplication . contents . includes ( 'MediaButtonPackage' ) ) {
485- // Read the BASE package name from build.gradle (namespace)
513+ // Resolve the BASE package name from build.gradle or build.gradle.kts
486514 // This is where the native module files are actually created
487- const buildGradlePath = path . join ( projectRoot , 'android' , 'app' , 'build.gradle' ) ;
488- let basePackageName = 'com.resgrid.unit' ; // Default fallback
489-
490- if ( fs . existsSync ( buildGradlePath ) ) {
491- const buildGradleContent = fs . readFileSync ( buildGradlePath , 'utf-8' ) ;
492- const namespaceMatch = buildGradleContent . match ( / n a m e s p a c e \s + [ ' " ] ( [ ^ ' " ] + ) [ ' " ] / ) ;
493- if ( namespaceMatch ) {
494- basePackageName = namespaceMatch [ 1 ] ;
495- }
496- }
515+ const basePackageName = resolveBasePackageName ( projectRoot ) ;
497516
498517 // Add import statement using the BASE package name (not the variant-specific package)
499518 // The native module files are created in the base package, not in variant packages like 'development'
0 commit comments