Skip to content

Instantly share code, notes, and snippets.

@jsuryahyd
Created July 9, 2019 11:27
Show Gist options
  • Save jsuryahyd/65c4c6fd8aa6c590fc0fafa2260dac9e to your computer and use it in GitHub Desktop.
Save jsuryahyd/65c4c6fd8aa6c590fc0fafa2260dac9e to your computer and use it in GitHub Desktop.
react native project readme

Native code

android picker styling

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:colorControlNormal">#00000000</item>
        <item name="android:spinnerStyle">@style/SpinnerStyle</item>
        <item name="android:spinnerItemStyle">@style/SpinnerItem</item>
        <item name="android:spinnerDropDownItemStyle">@style/SpinnerDropDownItem</item>
    </style>
    <style name="SpinnerStyle" parent="@android:style/Widget.Spinner">>
        <item name="android:background">@null</item>
    </style>

    <style name="SpinnerItem">
        <item name="android:fontFamily">Metropolis-Regular</item>
        <item name="android:textSize">@dimen/button_text_size</item>
    </style>

    <style name="SpinnerDropDownItem">
        <item name="android:textSize">@dimen/button_text_size</item>
        <item name="android:paddingLeft">15dp</item>
        <item name="android:layout_marginTop">@dimen/button_padding_top</item>
        <item name="android:layout_marginBottom">@dimen/button_padding_bottom</item>
        <item name="android:gravity">center_vertical</item>
        <!--  To align the text in the center -->
        <item name="android:fontFamily">Metropolis-Regular</item>
    </style>
</resources>

  • In the case of spinner ( Android Native Dropdown ) in order to set different font sizes for different device widths, we created two new folders, namely values-large and value-xlarge and dimens.xml file in each. In dimens.xmls, we set the fontsizes according to devies and mapped these values in a variable in styles.xml

  • To change the style (fontColor and fontFamily) of the picker items on Android, you have to change native code: https://stackoverflow.com/a/45254299/11125373

  • To remove the dropdown default icon, use this code

    <style name="SpinnerStyle" parent="@android:style/Widget.Spinner">>
        <item name="android:background">@null</item>
    </style> 
    
  • To change the fontSize for different devices, follow the steps mentioned in the below link https://stackoverflow.com/a/14528445/11125373

  • Different screen sizes in android: https://stackoverflow.com/a/38991428/11125373

THEME:

APP STATE

  • when ever we change the state of the app (background to foreground), the certain pages displaying dynamic data are reloaded.

Building for production

Android :

  • run npm install for installing/updating nodejs dependancies

  • configure dependancies by running react-native link

  • to run application in simulator or device -> react-native run-android

  • if npm run android-linux gives the following error

    ENOSPC: System limit for number of file watchers reached, watch '/home/tvisha/Desktop/Buvvas_mobile/mobile'
    
    Error: ENOSPC: System limit for number of file watchers reached, watch '/home/tvisha/Desktop/Buvvas_mobile/mobile'
    

    then run this ->

    echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
    
  • signing as explained below.

  • the following as explained in react-native documentation.Generate apk process - React native docs

    • edit gradle.properties with keystore file name and passwords.
    • add signing config inside build.gradle( the one inside android/app/),
    • add signing config inside buildTypes,
  • To prevent the screen orientation , add the following lines as XML attribute of activity tag in AndroidManifest.xml and rebuild the application

    android:screenOrientation="portrait"
    

    source : https://medium.com/building-with-react-native/how-to-lock-device-orientation-for-react-native-apps-android-ios-2x02-952c42cb51b1

  • To Rename the Android App, follow the below instructions:

    • Modify displayName in /app.json file

    • Modify app_name in android/app/src/main/res/values/strings.xml

      • and then run the below command:

        • cd android
        • gradlew clean
        • cd ..
        • react-native run-android

    reference : https://stackoverflow.com/a/53633206/11125373

  • To Rename the Android App Package Name , follow the below instructions:

    • Modify the following files and rename the package name:

      • settings.gradle

      • mainActivity.java

      • mainApplication.java

      • AndroidManifest.xml

      • android/app/build.gradle

      • google-services.json

      • splashActivity.java

      • package.json

      • BUCK file

      • .project

        Note: - Rename the folder name `/android/app/src/main/java/com/oldpackagename` to `/android/app/src/main/java/com/newpackagename`
        
    • Delete the package-lock.json and delete the node modules

    • Install the node modules

    • and then run the below command:

      • cd android
      • gradlew clean
      • cd ..
      • react-native run-android

IOS:

Additional resources

Errors and Suggestions

  • To get crash logs we shall use this following command ->

  • adb logcat -s ReactNative:V ReactNativeJS:V

  • Some packages might cause following sdk version license mismatch errors -

    •    platforms;android-25 Android SDK Platform 25
      To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.
      Alternatively, to transfer the license agreements from one workstation to another, see http://d.android.com/r/studio-ui/export-licenses.html
      
    - To resolve, run,
    ``` yes | sdkmanager --licenses ```
    
    -reference: https://stackoverflow.com/a/45782695
    
  • If you get the following error while running react-native run-android,

  • Execution failed for task ':app:transformClassesWithDexBuilderForDebug java.io.IOException: Could not delete path '/home/tvisha/Desktop/Buvvas_mobile/mobile/android/app/build/intermediates/transforms/dexBuilder/debug/62/android/arch/lifecycle/viewmodel/R.dex'

  • To resolve conflicts in version of various Google and firebase services, add the following line at the bottom in android/app/build.gradle

com.google.gms.googleservices.GoogleServicesPlugin.config.disableVersionCheck = true

  • If you get the following error while running react-native run-android,

  • Execution failed for task ':app:processDebugResources'. Failed to process resources, see aapt output above for details.

  • Command failed: ./gradlew installDebug

  • Change the following lines in build.gradle

  • compileSdkVersion 28 buildToolsVersion "28.0.2" minSdkVersion 16 targetSdkVersion 27

  • reference https://stackoverflow.com/a/54721823/11125373

Android Key Generation

  • source : https://facebook.github.io/react-native/docs/signed-apk-android
  • cd project_root/android/app
  • go to android/app directory,
  • run keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 or
  • run keytool -importkeystore -srckeystore my-release-key.keystore -destkeystore my-release-key.keystore -deststoretype pkcs12
  • Answer the questions.

Resource:https://developer.android.com/studio/publish/app-signing

Notifications - android

Note: - Notification Icons are been handled from the backend. To generate notification smallIcon

  • From android version lollpop onwards. When you are specifing the small icon, it should be of specific size of 18 x 18 px 24 x 24 px 36 x 36 px 48 x 48 px.

  • The important thing is the image should be with transparent background png file

  • Add your icon in mipmap folder.

  • source https://stackoverflow.com/a/53743456/11125373

Notifications - ios

react-native-firebase

target 'buvvas' do

pod 'RNFirebase', path:  '../node_modules/react-native-firebase/ios'
pod 'Firebase/Core'
pod 'Firebase/Messaging'

pod 'React', :path => '../node_modules/react-native'
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

end

  post_install do |installer|
    installer.pods_project.targets.each do |target|

      # The following is needed to ensure the "archive" step works in XCode.
      # It removes React & Yoga from the Pods project, as it is already included in the main project.
      # Without this, you'd see errors when you archive like:
      # "Multiple commands produce ... libReact.a"
      # "Multiple commands produce ... libyoga.a"

      targets_to_ignore = %w(React yoga)

      if targets_to_ignore.include? target.name
        target.remove_from_project
      end

    end
  end
  • added RnFirebase with path
  • run pod install
  • added some lines in appDelegate.h and appDelegate.m files
  • added "FirebaseAppDelegateProxyEnabled" - yes in info.plist
  • used firebase.messaging().onMessage(n=>{}) for ios purpose.
  • brought firebase.messaging().requestPermission block outside the hasEnabled if block.

Removing firebase from the project

  • To remove the firebase from the project, follow the following steps:
    • Remove the firebase node modules by npm uninstall react-native-firebase
    • Unlink the firebase by react-native unlink react-native-firebase
    • Delete package-lock.json file
    • Delete include ':react-native-firebase' and project(':react-native-firebase').projectDir = new File(rootProject.projectDir, '../node_modules react-native-firebase/android') from setting.gradle file
    • Delete implementation project(':react-native-firebase') from app/build.gradle
    • Remove all the receivers from RNFirebase from AndroidManifest.xml
    • Remove all the imports from io.invertase.firebase from MainApplication.java
    • Remove all the packages from RNFirebase from MainApplication.java
    • Clear gradlew by running cd android && ./gradlew clean
    • Remove all the node_modules by rm -rf node_modules and then run npm install

react-native-push-notifications

  • add the following code to APPDelegate.m

    // Required to register for notifications
      - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
      {
    
      [RCTPushNotificationManager didRegisterUserNotificationSettings:notificationSettings];
      }
    // Required for the register event.
      - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
      {
      [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
      }
      // Required for the notification event. You must call the completion handler after handling the remote notification.
      - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
      fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
      {
      [RCTPushNotificationManager didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
      }
      // Required for the registrationError event.
      - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
      {
      [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error];
      }
      // Required for the localNotification event.
      - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
      {
      [RCTPushNotificationManager didReceiveLocalNotification:notification];
      }```
    
    
  • for foreground notifications - we must trigger ourselves local notifications. zo0r/react-native-push-notification#275 (comment)

    -(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
      completionHandler(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge);
    }
    
    // Called when a user taps on a notification in the foreground
    - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler
    
    {
      NSMutableDictionary *userData = [NSMutableDictionary dictionaryWithDictionary:response.notification.request.content.userInfo];
      [userData setObject:@(1) forKey:@"openedInForeground"];
      [RCTPushNotificationManager didReceiveRemoteNotification:userData];
      completionHandler();
    }
    
    • add these two lines in first function (didlaunch...)
    UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
    center.delegate = self;
    
    • and add these lines in onNotification Function in JS
     // Check if opened from forground
    if (notificationObj.data.openedInForeground) {
        notificationObj.userInteraction = true;
    }
    
    if (notificationObj.userInteraction)
    {
      this.onNotificationCallback?.(notification);
    }
    
    // Only call callback if not from foreground
    if (!notificationObj.data.openedInForeground) {
      notificationObj.finish(PushNotificationIOS.FetchResult.NoData);
    }
    
  • To fill the ios fullscreen use the following code :

"ios": {
    "bundleIdentifier": "your bundle identifier",
    "supportsTablet": true
    }

IMPORTANT NOTES AND LINKS:

Few of the solutions of the compile and run time errors that we would be encountering while installing the application are mentioned here: https://developer.android.com/studio/known-issues

  • To resolve the android dependency com-android-supportsupport-v4 has different version, we have added the following lines of code in android/build.gradle (After adding bluetooth printer package)
   subprojects {
    project.evaluationDependsOn(':app')
    project.configurations.all {
        resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.android.support'
                    && !details.requested.name.contains('multidex') ) {
                details.useVersion "27.1.0"
            }
        }
      }
    }

Reference: https://stackoverflow.com/a/50507056/11125373

  • To Resolve the below error , you have to remove the .git file (find the hidden folder by bash command ls -la)

npm ERR! path /home/tvisha/Desktop/Buvvas_mobile/mobile/node_modules/react-native-push-notification
npm ERR! code EISGIT
npm ERR! git /home/tvisha/Desktop/Buvvas_mobile/mobile/node_modules/react-native-push-notification: Appears to be a git repo or submodule.
npm ERR! git     /home/tvisha/Desktop/Buvvas_mobile/mobile/node_modules/react-native-push-notification
npm ERR! git Refusing to remove it. Update manually,
npm ERR! git or move it out of the way first.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/tvisha/.npm/_logs/2019-05-06T04_56_36_901Z-debug.log

- The library could be anything, other than "react-native-push-njotification"

Reference magus/react-native-facebook-login#313 (comment)

  • After Login, Home Pages are realoaded because of the way Router.js is built, since the page is reloaded any eventListners and setStates calls inside lifecycle methods (componentWillMount, componentDidMount) will throw error.

This has been reslovced by avoiding event listners and setstate calls by using Redux.

The other way to do is

  async componentDidMount() {
    this._isMounted = true;
    this._isMounted && this.setState({ loading: false });
  }

  componentWillUnmount() {
    this._isMounted = false;
  }
  • For allowing google to do indexing of app: Resource https://stackoverflow.com/a/34368811/11125373

  • To solve the following issue: :app:transformDexArchiveWithExternalLibsDexMergerForDebug, -Go to android/app build.gradle -In defaultConfig add multiDexEnabled true

To Resolve the conflits of react-native-html-to-pdf duplicate package, we deleted the example folder which was present in the respective node_module folder

LINTING AND APP OPTIMISING

  • There might be unused codes and resources that might be used in an application, to find those , follow the below process

-go to android folder -run the command ./gradlew lint

At the end of the lint it will generate a report in the HTML file. Follow the instructions mentioned in the report to optimise the app

Resource:[https://developer.android.com/topic/performance/reduce-apk-size.html](https://developer.android.com/topic/performance/reduce-apk-size.html

  • There might be features in AndroidManiFest.xml that might not be used in the application, to find them and remove it, flow the below process: -go to the folder where you find app-debug.apk run the following command :apkanalyzer -h apk features --not-required app-debug.apk It will list out all the unused features that are not required. Remove those.

FLOW

Check the below link to add the flow in the project https://stackoverflow.com/a/45696516/11125373

CHANGES AFTER APPLYING TO GOOGLE PLAYSTORE

Concept of Expansion File: https://stackoverflow.com/a/25768748/11125373

YET TO CHECK:

apksigner:https://developer.android.com/studio/command-line/apksigner zipalign:https://developer.android.com/studio/command-line/zipalign apksigner and zipalign in react native :https://gist.github.com/marty-wang/5a71e9d0a6a2c6d6263c

APP ICON:

To add an app icon in android, we shall be placing the icons in the all the drawable folders.

APP INSTALL ISSUE:

If we get issue like com.android.builder.testing.api.DeviceException: No online devices found

Then open the System Moniter, kill the adb and re-run react-native run-android

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment