Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current Restore this Version View Page History

« Previous Version 3 Current »


Crear proyecto base en React Native

  • Crea un nuevo proyecto de React Native:

npx react-native@latest init NombreDeProyecto --template react-native-template-typescript
  • Inicia Metro en el directorio de tu proyecto:

yarn start
  • Ejecuta tu proyecto de React Native en Android y iOS:

yarn android
yarn ios

Integrar proyecto existente Android a proyecto React Native

NOTA: Antes de comenzar, verifica que tu proyecto Android compila correctamente con Android Studio y ejecútalo en un emulador o dispositivo físico.

  • En tu proyecto de React Native, ve al directorio /android y elimina todo el contenido. Asegúrate de eliminar también los elementos ocultos (en MacOS: CMD + Shift + .)

  • Copia tu proyecto existente Android en tu proyecto React Native en el directorio /android.

  • Verifica que tu package.json contenga las siguientes propiedades, si no es así, agrégalas:

{
	"name": "MyReactNativeApp",
	"version": "0.0.1",
	"private": true,
	"scripts": {
		"start": "yarn react-native start"
	}
}
  • Abre una terminal en la raíz de tu proyecto React Native y ejecuta el siguiente comando para agregar las dependencias (/node_modules):

yarn add react-native
  • Agrega en el archivo settings.gradle la siguiente línea:

includeBuild('../node_modules/react-native-gradle-plugin')
  • Agrega en el archivo build.gradle en la raíz de tu proyecto la siguiente dependencia:

buildscript {
	repositories {
		google()
		mavenCentral()
	}
	dependencies {
			classpath("com.android.tools.build:gradle:7.3.1")
			classpath("com.facebook.react:react-native-gradle-plugin")
	}
}
  • Agrega en el archivo app/build.gradle (a nivel de app) las siguientes dependencias:

apply plugin: "com.android.application"
apply plugin: "com.facebook.react"

repositories {
	mavenCentral()
}

dependencies {
	// Other dependencies here
	implementation "com.facebook.react:react-android"
	implementation "com.facebook.react:hermes-android"
}
  • Agrega en el archivo settings.gradle lo siguiente (autolinking):

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
  • Agrega al final del archivo app/build.gradle (a nivel de app) lo siguiente (autolinking):

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
  • Agrega el permiso de internet en el AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET" />
  • Agrega lo siguiente en el AndroidManifest.xml (solo se usa en el modo de desarrollo cuando se vuelve a cargar JavaScript desde el servidor de desarrollo, por lo que puede quitarlo en las compilaciones de lanzamiento si es necesario):

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
  • Agrega la siguiente opción en el AndroidManifest.xml:

<!-- ... -->
<application
	android:usesCleartextTraffic="true" tools:targetApi="28" >
	<!-- ... -->
</application>
<!-- ... -->
  • En tu App.tsx agrega lo siguiente (register component):

import React from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';

const App = () => {
	return (
		<View style={styles.container}>
			<Text style={styles.hello}>Hello, World</Text>
		</View>
	);
};

var styles = StyleSheet.create({
	container: {
		flex: 1,
		justifyContent: 'center',
	},
	hello: {
		fontSize: 20,
		textAlign: 'center',
		margin: 10,
	},
});

export default App;

AppRegistry.registerComponent(
	'MyReactNativeApp',
	() => App,
);
  • Para las siguientes modificaciones, abre el proyecto Android que integraste dentro del directorio /android de tu proyecto React Native. Al abrirlo, comenzará a compilar el proyecto automáticamente. Si te da el siguiente error al compilar This declaration is experimental and its usage must be marked with '@kotlin.ExperimentalStdlibApi' or '@OptIn(kotlin.ExperimentalStdlibApi::class)’ entonces modifica en el archivo gradle-wrapper.properties la propiedad distributionUrl para que quede de la siguiente forma y vuelve a compilar el proyecto:

distributionUrl=https\\://services.gradle.org/distributions/gradle-7.5.1-all.zip
  • En tu activity launcher (en el caso de la app de Diiki B2C, agregar en la clase BaseActivityBinder ), en el método onCreate agrega lo siguiente:

import android.os.Build
import android.provider.Settings

...

companion object {
	const val OVERLAY_PERMISSION_REQ_CODE = 1  // Choose any value
}

...

// Inside onCreate method:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
	if(!Settings.canDrawOverlays(this)) {
		val intent = Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
		Uri.parse("package: $packageName"))
		startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
	}
}
  • Agrega fuera del método onCreate lo siguiente (en el caso de la app de Diiki B2C, agregar en la clase BaseActivityBinder ):

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (!Settings.canDrawOverlays(this)) {
                    // SYSTEM_ALERT_WINDOW permission not granted
                }
            }
        }
        reactInstanceManager?.onActivityResult(this, requestCode, resultCode, data)
    }
  • Agrega la siguiente configuración en tu activity launcher (algunas van dentro del método onCreate) (en el caso de la app de Diiki B2C, agregar en la clase BaseActivityBinder ):

class MyReactActivity : Activity(), DefaultHardwareBackBtnHandler {
    private lateinit var reactRootView: ReactRootView
    private lateinit var reactInstanceManager: ReactInstanceManager
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        SoLoader.init(this, false)
        reactRootView = ReactRootView(this)
        val packages: List<ReactPackage> = PackageList(application).packages
        // Packages that cannot be autolinked yet can be added manually here, for example:
        // packages.add(MyReactNativePackage())
        // Remember to include them in `settings.gradle` and `app/build.gradle` too.
        reactInstanceManager = ReactInstanceManager.builder()
            .setApplication(application)
            .setCurrentActivity(this)
            .setBundleAssetName("index.android.bundle")
            .setJSMainModulePath("index")
            .addPackages(packages)
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build()
        // The string here (e.g. "MyReactNativeApp") has to match
        // the string in AppRegistry.registerComponent() in index.js
        reactRootView?.startReactApplication(reactInstanceManager, "MyReactNativeApp", null)
        setContentView(reactRootView)
    }

    override fun invokeDefaultOnBackPressed() {
        super.onBackPressed()
    }
}
  • En Android Studio ve a File > Sync Project With Gradle Files .

  • En el AndroidManifest.xml agrega el siguiente theme a tu activity launcher:

<activity
	android:name=".MyReactActivity"
	android:label="@string/app_name"
	android:theme="@style/Theme.AppCompat.Light.NoActionBar">
</activity>
  • Agrega lo siguiente a tu activity launcher (en el caso de la app de Diiki B2C, agregar en la clase BaseActivityBinder ):

override fun onPause() {
	super.onPause()
	reactInstanceManager.onHostPause(this)
}

override fun onResume() {
	super.onResume()
	reactInstanceManager.onHostResume(this, this)
}

override fun onDestroy() {
	super.onDestroy()
	reactInstanceManager.onHostDestroy(this)
	reactRootView.unmountReactApplication()
}

override fun onBackPressed() {
    reactInstanceManager.onBackPressed()
    super.onBackPressed()
}

override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
    if (keyCode == KeyEvent.KEYCODE_MENU && reactInstanceManager != null) {
        reactInstanceManager.showDevOptionsDialog()
        return true
    }
    return super.onKeyUp(keyCode, event)
}
  • Ejecuta la app desde Android Studio para confirmar que no presente errores. Puede ser que se requieran actualizar determinadas dependencias en app/build.gradle.

  • Si ya no tienes errores con el paso anterior, ejecuta la app desde el proyecto de React Native. Abre una terminal, ve a tu proyecto e inicia Metro con el siguiente comando:

yarn start
  • Ejecuta el proyecto Android con el siguiente comando:

yarn android --mode wii2debug --main-activity com.gigigo.wii.view.splash.SplashActivity --appId com.gigigo.wii.debug

Issues Android (15 Mar 2023):

  • Problema con consola de depuración Metro (React Native). No detecta los comandos “reload (r)", "open developer menu (d)", da el siguiente error (ver imagen más abajo): No apps connected. Sending "reload" to all React Native apps failed. Make sure your app is running in the simulator or on a phone connected via USB . Cabe mencionar que si detecta Metro al iniciar la app desde React Native (muestra una barra de progreso al compilar y ejecutar la app) pero esos comandos no los detecta. En la documentación oficial mencionan sobre agregar al AndroidManifest.xml la propiedad android:usesCleartextTraffic="true" para que Metro establezca esa comunicación con la app, esa propiedad se agregó pero el problema persiste.

SOLUCIÓN: Se “mueve” la lógica de integración Android del activity launcher (SplashActivity) a la clase BaseActivityBinder . Esta clase tiene el papel de ser la superclase o clase padre de la mayoría de las pantallas (activity) del proyecto B2C Android. Al hacer esta modificación y usar los comandos en la terminal de Metro “reload (r)" y "open developer menu (d)" se eliminó el error y ya muestra el menú en modo desarrollador (ver imagen abajo).


Referencias:

Integration with Existing Apps · React Native

Integrating react native with existing Android and iOS native projects