Categories
Technology

Implementing Biometric Login in React Native: A Comprehensive Guide for iOS

Implementing Biometric Login in React Native: A Comprehensive Guide for iOS

Biometric authentication has become an essential feature for mobile applications, providing users with a convenient and secure way to access their accounts. With biometrics, users can authenticate using Face ID, Touch ID, or fallback to device passcodes. This guide explains how to implement biometric login in a React Native application by bridging native iOS code with your React Native app.

Why Biometric Authentication?

In today’s digital landscape, security and user experience are paramount. Biometric authentication offers:

  • Quick and seamless login experience.
  • Enhanced security compared to traditional password methods.
  • Support for multiple authentication types (Face ID, Touch ID, device credentials).

    What You’ll Learn
  • How to check biometric authentication availability on iOS devices.
  • How to implement biometric authentication with a fallback to device credentials.
  • How to bridge native iOS code with React Native.
  • How to use the functionality in your React Native app.

    Step 1: Permissions Required for Biometric Authentication:
  • iOS requires permission and configuration in your app to access biometric features. Update your app’s Info.plist file to include the following keys:
  • <key>NSFaceIDUsageDescription</key>
  • <string>We use Face ID to authenticate you securely.</string>
  • <key>NSBiometricUsageDescription</key>
  • <string>We use biometric authentication to enhance your security.</string>
  • These keys ensure that your app requests permission from the user to use Face ID or Touch ID.

    Step 2: Checking Biometric Authentication Availability:

    We need to verify whether biometric authentication is supported on the device. This is done using the LAContext class from Apple’s LocalAuthentication framework.

    Native Code (iOS)

Create a method in your native module to check biometric authentication availability:
import LocalAuthentication

import React

@objc(NativeBridge)

class NativeBridge: NSObject {

    @objc

    func checkBiometricAuthAvailable(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {

        let context = LAContext()

        var error: NSError?

        let isAvailable = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error)

        if isAvailable {

            resolve(true)

        } else {

            resolve(false)

        }

    }

}

This method checks if biometric authentication (Face ID or Touch ID) is available on the device and returns a boolean value.

Step 3: Implementing Biometric Authentication:

Now, let’s create a method to authenticate users using biometrics. If biometrics aren’t available, we’ll fallback to device passcodes.

@objc

func authenticateWithBiometric(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {

    let context = LAContext()

    let reason = “Authenticate to access your account.”

    context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in

        if success {

            resolve(“AUTH_SUCCESS”)

        } else if let error = error as NSError? {

            let errorCode = error.code

            switch errorCode {

            case LAError.authenticationFailed.rawValue:

                reject(“AUTH_FAILED”, “Authentication failed.”, nil)

            case LAError.userCancel.rawValue:

                reject(“USER_CANCELLED”, “Authentication was cancelled by the user.”, nil)

            case LAError.userFallback.rawValue:

                reject(“USER_FALLBACK”, “User chose to use fallback authentication method.”, nil)

            case LAError.biometryNotAvailable.rawValue:

                reject(“BIOMETRY_NOT_AVAILABLE”, “Biometric authentication is not available.”, nil)

            case LAError.biometryNotEnrolled.rawValue:

                reject(“BIOMETRY_NOT_ENROLLED”, “Biometric authentication is not enrolled.”, nil)

            default:

                reject(“AUTH_ERROR”, “An unknown error occurred.”, nil)

            }

        }

    }

}

This method:

  • Displays the biometric authentication prompt.
  • Authenticates the user with Face ID, Touch ID, or device passcode.
  • Handles success, errors, and user cancellation.

    Step 4: Bridging Native Code with React Native :

To make these methods accessible in React Native, create a bridging module.
NativeBridge.m

#import “React/RCTBridgeModule.h”

@interface RCT_EXTERN_MODULE(NativeBridge, NSObject)

RCT_EXTERN_METHOD(checkBiometricAuthAvailable: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject)

RCT_EXTERN_METHOD(authenticateWithBiometric: (RCTPromiseResolveBlock)resolve reject: (RCTPromiseRejectBlock)reject)

@end


Step 5: Register the Native Module:

Ensure the module is registered in your iOS app.
AppDelegate.swift

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate {

    …

    // Ensure React Native bridge is initialized properly

}

Step 6: React Native Integration:

In your React Native app, create utility functions to call the native methods.

import { NativeModules } from ‘react-native’;

export const checkBiometricAuthAvailability = async () => {

  try {

    const isAvailable = await NativeModules.NativeBridge.checkBiometricAuthAvailable();

    return isAvailable;

  } catch (error) {

    return false;

  }

};

export const authenticateWithBiometric = async () => {

  try {

    const result = await NativeModules.NativeBridge.authenticateWithBiometric();

    return result === ‘AUTH_SUCCESS’;

  } catch (error) {

    console.log(‘Authentication Error:’, error);

    return false;
}
};

Step 7: Using Biometric Authentication:

Use these functions in your React Native components to check and authenticate users.

import React, { useState } from ‘react’;

import { View, Button, Text } from ‘react-native’;

import { checkBiometricAuthAvailability, authenticateWithBiometric } from ‘./BiometricUtils’;

const App = () => {

  const [authStatus, setAuthStatus] = useState(”);

  const handleLogin = async () => {

    const isAvailable = await checkBiometricAuthAvailability();

    if (!isAvailable) {

      setAuthStatus(‘Biometric authentication not available.’);

      return;

    }

    const isAuthenticated = await authenticateWithBiometric();

    setAuthStatus(isAuthenticated ? ‘Authenticated!’ : ‘Authentication Failed.’);

  };

  return (

    <View>

      <Button title=”Login with Biometrics” onPress={handleLogin} />

      <Text>{authStatus}</Text>

    </View>

  );

};

export default App;

Next Steps

  • Implement credential storage using Keychain for enhanced security.
  • Add comprehensive error handling and user feedback.
  • Expand the feature to support additional scenarios (e.g., two-factor authentication).

Conclusion

With this guide, you’ve added biometric authentication to your React Native app on iOS, offering users a secure and seamless login experience. Follow similar steps for Android to ensure feature parity across platforms.

Categories
Technology

iPhone 16 



New features of iPhone 16: 

  1. Vertical Cameras for Spatial Video Capture. 
  1. New Camera Control Button. 
  1. New Action Button 
  1. A18 Chipset. 
  1. Performance and Battery Life. 
  1. Connectivity and Features. 
  1. Apple Intelligence Features. 

    1. Vertical Cameras for Spatial Video Capture: 

a. Spatial video technology: iPhone 16 features vertically aligned cameras specifically designed for spatial video capture, enabling immersive 3D-like video content. 

b. Improved Ultra-Wide camera enabling macro photography. 

c. The new vertical layout allows better alignment and collaboration between the lenses for depth perception, creating richer media. 

2. New Camera Control Button: 

a. Advanced camera controls: The iPhone 16 introduces a dedicated Camera Control button to allow easier and quicker access to camera settings. 

b. Streamlined capture: With a single tap, you can switch between different camera modes (photo, video, portrait, night mode, etc.), control exposure, or toggle settings like flash and Live Photos. 

c. Improved user experience: Provides quick adjustments during video recording and photo taking without navigating multiple menus. 

3. New Action Button :  

a. The Action Button replaces the traditional mute switch on the side of the iPhone. 

b. Customizable: You can program it to perform various actions, such as launching the camera, starting a voice memo, toggling silent mode, launching an app, or running a shortcut. 

c. User-defined: It offers customization through settings, letting you choose the specific action it performs depending on how you press it (e.g., press and hold, double press). 

d. Dynamic functionality: Can also be integrated with Focus modes to change actions based on your current focus settings. 

4. A18 Chipset: 

a. The new A18 Bionic chipset brings a significant boost in both CPU and GPU performance. 

b. Faster processing: Improved neural engine capabilities for faster AI and machine learning tasks, such as image recognition and natural language processing. 

c. Enhanced efficiency: Better power management leads to improved battery life, particularly for resource-intensive tasks like gaming, 3D rendering, and video editing. 

d. Advanced graphics: The A18 introduces advanced graphics rendering, enabling smoother gameplay and better performance for AR/VR applications 

5. Performance and Battery Life: 


a. Powered by the all-new A18 chip, delivering up to 30% faster CPU and up to 40% faster GPU compared to the A16 Bionic 

b. Larger batteries achieved through redesigning the phone’s interior. 

c. Significant boost in battery life – up to 22 hours video playback for iPhone 16 and 27 hours for iPhone 16 Plus. 

6. Connectivity and features: 

a. Support for Wi-Fi 7 connectivity. 

b. Bluetooth 5.3 support. 

c. Apple Intelligence integration, allowing for personal intelligence features. 



7.Apple Intelligence Features (Arrived in October): 

a. On-device AI: Apple is rolling out new Apple Intelligence features powered by the A18 chipset in October. 

b. Advanced machine learning: These features enhance personalization, app recommendations, and predictive text functionalities. 

c. Smarter Siri: Siri will get more powerful with on-device processing, making it faster and more responsive. 

d. Enhanced Photos and Camera: AI-driven enhancements in photo editing, real-time adjustments, and object recognition across apps. 

Categories
Technology

React Native Redux vs  Context API 

React Native Redux vs  Context API 

Redux : 
       Redux is a state management library for JavaScript applications, commonly used with React. It provides a centralized store that holds the entire application’s state, allowing you to manage and access state consistently across the application. 

UseContext : 
        useContext is a React hook that allows components to access and share data across the component tree without the need for props drilling. It works with the Context API, which enables you to create a context and a provider that wraps around parts of your component tree. Components within that subtree can then consume the context directly using useContext, giving them direct access to shared state or data. 

Props drilling :  

          Props drilling is a concept in React where data (props) is passed from a parent component to deeply nested child components. When child components several levels down the component tree need access to the data, you must pass the data through each intermediary component as props, even if those intermediary components don’t actually use the data. 

Problems with Props Drilling: 

  1. Repetitive Code: Every intermediary component must accept and pass along the props, even if it doesn’t use them. 
  1. Maintenance Issues: If you need to add, change, or remove a prop, you must update all components in the path, making the code harder to maintain. 
  1. Scalability: As the app grows, props drilling can make it difficult to manage data, especially when data is needed in many parts of the app. 

useContext and Redux as Solutions to Props Drilling 

Both useContext and Redux help manage global state in React, enabling you to avoid props drilling by providing state to components directly, regardless of their nesting level. 

1. useContext 

The Context API in React allows you to create a context, which provides data directly to any component that needs it, without needing to pass it down through every level in between. 

How it Helps: 

  • With useContext, you can avoid props drilling by wrapping a part of your component tree with a Provider and accessing the data with useContext in any descendant component. 
  • It’s ideal for smaller or medium-sized applications where a piece of data needs to be shared by multiple components, but the app doesn’t require complex state management. 

 
2. Redux 

Redux is a state management library that holds the entire application state in a single store. Components can access and update this state directly, which eliminates the need for props drilling across the application. 

How it Helps: 

  • Redux provides a global store for state, so components can access and update state directly without passing props. 
  • This makes Redux particularly suitable for larger applications with complex state management needs, as it supports middleware for handling asynchronous actions and has powerful debugging tools. 

Both useContext and Redux can help avoid props drilling and make the component tree cleaner and more maintainable. The choice depends on the complexity and scale of your application. 

Differences between Redux and useContext 

React Native Redux vs. useContext: Main Differences 

  1. State Management Style: 
  • Redux: Centralized, single global store. All state is held in one place, and components can access and update it via actions and reducers
  • useContext: Decentralized, uses React’s Context API. State is shared between components without requiring a global store, but state is typically scoped to a subtree of components. 
  1. Scalability: 
  • Redux: Suitable for larger applications with complex state logic because it offers predictable state management patterns. More structure and tooling (like middlewares) for handling side effects. 
  • useContext: Better for smaller apps or for managing simpler, localized state. It can become challenging to maintain and scale with complex applications due to lack of middleware or action-based state flow. 
  1. Boilerplate: 
  • Redux: More boilerplate code (setting up store, reducers, actions). This is often necessary for the stricter pattern but can be cumbersome. 
  • useContext: Less boilerplate; integrates seamlessly into React with hooks. It’s lighter but doesn’t have the strict structure that Redux imposes. 
  1. Side Effects Handling: 
  • Redux: Provides support for handling side effects via middleware like redux-thunk or redux-saga
  • useContext: No native way to handle side effects. You would need to use other hooks like useReducer or useEffect to manage side effects, which can become complicated as the app grows. 
  1. Debugging Tools: 
  • Redux: Redux DevTools provide advanced debugging and state tracking capabilities, making it easier to trace state changes. 
  • useContext: No built-in debugging tools like Redux. State changes are harder to track, especially in larger apps. 
  1. Performance: 
  • Redux: Uses selectors to optimize performance by preventing unnecessary re-renders when only specific parts of the state are updated. 
  • useContext: Any context update will cause all consuming components to re-render, which can lead to performance issues in larger apps. 

Installation and Usage 

1. Redux (React-Redux) in React Native 

Installation:   npm install @reduxjs/toolkit react-redux 

2. Basic SetupCreate the store 

3. Provide the store: Wrap your app with the <Provider> component to give access to the store. 

4. Using Redux in a component

a. Access state: Use useSelector to access the store’s state. 

b. Dispatch actions: Use useDispatch to dispatch actions. 



useContext with React Native 

  1. Installation: No external package needed. 
     
  1. Basic Setup


    a. Create a context: 


b. Using context in a component

Access context: Use useContext to access the context value. 

c. Provide the context: Wrap the component tree that needs access to the context inside the provider. 



When to Use Redux vs. useContext? 

  1. Use Redux when: 

a. Your app has a large state that needs to be shared across many unrelated components. 

b. You need predictable and maintainable state management with debugging and middleware support. 

c. Your state logic involves complex transformations or side effects (i.e., asynchronous operations). 

  1. Use useContext when: 

a. Your app is small or medium-sized, and you need to share a small amount of state between a few components. 

b. You want a simple, quick solution without introducing much boilerplate. 

c. Your state is localized to certain component trees and doesn’t require complex state logic or side effects. 

Categories
Technology

Automate and deploy Android and iOS Builds using Fastlane and Self-Hosted Runners

Automate and deploy Android and iOS Builds using Fastlane and Self-Hosted Runners

Introduction :

Why automate Android and iOS builds?

Automating Android and iOS builds focuses on the build and deployment steps in the Software Development Life Cycle (SDLC) to save time. By automating these processes, we reduce manual intervention, minimize errors, and ensure faster and more consistent delivery of application updates.

Continuous Integration and Continuous Deployment (CI/CD) pipelines are crucial in modern mobile app development. They ensure that code changes are automatically built, tested, and deployed, reducing manual effort and the risk of errors.

Introduction to CI/CD Pipeline

Continuous Integration (CI) and Continuous Delivery (CD) are practices that enable development teams to deliver code changes more frequently and reliably.

Continuous Integration (CI): Developers merge their code changes into a central repository. Automated builds and tests are run to ensure that the new code does not introduce any bugs or break existing functionality.

Continuous Delivery (CD): Once code passes CI, it is automatically deployed to a staging environment. From there, it can be released to production with a manual approval step.

Tools: Jenkins, GitHub Actions, GitLab CI, CircleCI, Travis CI.

Benefits of a CI/CD Pipeline

  • Faster Development Cycles: Automated processes reduce the time required for code integration and deployment.
  • Improved Code Quality: Continuous testing ensures that code changes do not introduce new bugs or regressions.
  • Enhanced Collaboration: Teams can collaborate more effectively with a streamlined workflow.
  • Reduced Manual Effort: Automation minimizes manual intervention, reducing human error and freeing up developer time for more critical tasks.

The primary goal is to ensure that code changes are integrated and delivered to production rapidly and safely.

Introduction to Self-Hosted Runners

Self-hosted runners are machines that you manage and maintain to run GitHub Actions workflows. Unlike GitHub-hosted runners, which are managed by GitHub, self-hosted runners provide more control over the hardware, operating system, and software environment.

Step-by-Step Guide

  • Create a Runner:     
    a. Go to your repository on GitHub.
    b. Navigate to Settings > Actions > Runners > New self-hosted runner.
    c. Choose the operating system for your runner (Linux, macOS, or Windows).
  •  Download and Configure the Runner: Follow the provided steps to setup self-       hosted runners.

Introduction to Fastlane

  • Fastlane is an open-source platform designed to streamline the process of building, testing, and releasing mobile applications for iOS and Android. It automates many repetitive tasks in the app development lifecycle, making it easier and faster for developers to deploy their apps.

Setting Up Fastlane for Android and iOS

  • Installing Fastlane :  
                              Fastlane can be installed in multiple ways. The preferred method is with Bundler. Fastlane can also be installed directly through Homebrew (if on macOS). It is possible to use macOS’s system Ruby, but it’s not recommended, as it can be hard to manage dependencies and cause conflicts.
  • Setting up Fastlane :   
         Navigate your terminal to your project and run ‘Fastlane init’ inside android and iOS directory.

        This will create Fastlane folder inside our project android and iOS directory.

Deploy Android and iOS Builds to Firebase

Android fastlane code

iOS fastlane code

Integrating Fastlane with GitHub Actions

Integrating Fastlane with CI/CD (Github Actions) pipelines is essential for automating the build, test, and deployment processes for mobile applications. This integration ensures that each code change is automatically built, tested, and deployed, improving efficiency and reducing the risk of human errors.

Explanation:

  • Trigger: The pipeline runs on push events to the main branch and on pull requests
    Or on Workflow_dispatch on manual trigger.
  • Jobs:
    a. Build: Checks out the code, sets up the JDK, caches Gradle dependencies, builds the app, runs unit tests, and uploads the APK.
    b. Deploy: Deploys the apk or aab to Firebase App Distribution/Playstore/Appstore (after the build job succeeds).

 Workflow in Github Actions

Common Issues and Troubleshooting

Categories
Technology

Android Letter Boxing

Android letterboxing refers to the technique used to maintain aspect ratio compatibility when running apps on devices with different screen sizes and aspect ratios. It ensures that the app’s content remains within a specified safe area, preventing stretching or distortion on non-standard screens.

Purpose: To enhance user experience by allowing apps to adapt gracefully to various device configurations, especially on larger screens where the aspect ratios differ significantly from traditional smartphones.

Features of Android Letterboxing

  • Aspect Ratio Preservation:

Android letterboxing preserves the original aspect ratio of the app’s content, preventing visual distortions or stretching on devices with different aspect ratios.

  •   Safe Area Definition:                                                     
    It defines a safe area within which the app’s essential content is displayed, ensuring that crucial UI elements remain visible and usable on all screen sizes.
  • Uniform User Experience:
    Ensures a consistent user experience across various Android devices by adapting the app’s layout and content presentation dynamically.
  • Compatibility:
    Supports different screen sizes and resolutions, maintaining compatibility with a wide range of Android devices, including tablets and foldable phones.

Implementing Android Letterboxing

Design Considerations

  • Define Safe Areas: Identify and define the critical UI elements and content that must remain visible and accessible across different screen sizes.
  • Aspect Ratio Handling: Design UI layouts and resources to adapt flexibly to varying aspect ratios while maintaining visual integrity.
  • Code snippet :

{ height, width } = Dimensions.get(‘window’)

 aspectRatio = height / width

 Mindimension = Math.min(height, width)

(mindimension >= 600) || (aspectRatio < 1.6)

Implementation Steps

  • Use Constraint Layout: Utilize Constraint Layout with guidelines and constraints to define flexible UI layouts that adjust to different screen sizes.
  • Dynamic Dimension Handling: Implement dynamic dimension calculations and adaptive layout strategies to adjust UI elements based on the available screen space.
  • Resource Qualifiers: Use resource qualifiers (res/layout-wXXXdp) to provide different layout configurations optimized for specific screen widths or aspect ratios.
  • Code snippet :

Boolean isTabletAndroid = getResources().getBoolean(R.bool.isTabletAndroid)

Testing and Validation

  • Device Emulators: Test the app on various Android emulators to simulate different screen sizes and aspect ratios.
  • Real Device Testing: Conduct thorough testing on real devices, including devices with non-standard aspect ratios (e.g., foldable phones), to validate the effectiveness of the letterboxing implementation.

Best Practices

  • Consistency: Maintain a consistent UI design across different devices by adhering to Material Design guidelines and platform-specific UI standards.
  • Performance Optimization: Optimize app performance by minimizing unnecessary UI redraws and ensuring efficient layout rendering on all supported devices.
  • Accessibility: Ensure accessibility considerations are integrated into the letterboxing design, making UI elements accessible and usable for all users.

Conclusion

In conclusion, Android letterboxing is a crucial technique for ensuring app compatibility and maintaining visual integrity across diverse Android devices. By implementing letterboxing effectively and following best practices, developers can deliver a seamless user experience regardless of device screen size or aspect ratio.

References