How To Implement In-App Update in React-Native for Android :-

How To Implement In-App Update in React-Native for Android :-

Implementing In-App Updates in a React Native Application: A Comprehensive Guide

In today's fast-paced digital landscape, ensuring that users have access to the latest features and updates of your app is crucial for maintaining user engagement and satisfaction. One effective way to achieve this is by implementing in-app updates, allowing users to download and install updates directly within the app without needing to visit the Google Play Store. In this post, I'll walk you through the process of integrating in-app updates into your React Native application, leveraging native Android capabilities.

Why In-App Updates?

1. Seamless User Experience: In-app updates eliminate the need for users to leave your app, providing a smooth and uninterrupted experience.

2. Prompt Bug Fixes: Quickly address critical issues and push patches directly to users, enhancing reliability.

3. Faster Feature Adoption: Encourage users to explore new features more rapidly, boosting engagement.

4. Increased User Retention: Keep users coming back by consistently offering improved experiences and functionalities.

Step-by-Step Implementation

Step 1: Add Dependencies

First, add the necessary dependencies to your Android project. These dependencies enable in-app update functionality using Google's Play Core library.

  • Open your android/app/build.gradle file and add the following:

dependencies {
    implementation 'com.google.android.play:app-update:2.1.0'
    implementation 'com.google.android.play:app-update-ktx:2.1.0'
}        

Ensure that the Google Maven repository is included in your project's android/build.gradle:

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}        

Step 2: Create a Native Module

Since React Native doesn't directly support in-app updates, we need to create a native module to bridge Android functionality with React Native.

  1. Create the Java Class

Navigate to android/app/src/main/java/com/yourproject/ and create a new Java class named InAppUpdateModule.java.

Implement In-App Update Logic

Here’s the core implementation for in-app updates:


package com.yourproject;

import android.app.Activity;
import android.content.IntentSender;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.google.android.play.core.appupdate.AppUpdateManager;
import com.google.android.play.core.appupdate.AppUpdateManagerFactory;
import com.google.android.play.core.appupdate.AppUpdateType;
import com.google.android.play.core.install.InstallStateUpdatedListener;
import com.google.android.play.core.install.model.AppUpdateInfo;
import com.google.android.play.core.install.model.UpdateAvailability;

public class InAppUpdateModule extends ReactContextBaseJavaModule {

    private final int MY_REQUEST_CODE = 500;
    private final AppUpdateManager appUpdateManager;
    private final Activity activity;

    public InAppUpdateModule(ReactApplicationContext reactContext) {
        super(reactContext);
        this.activity = getCurrentActivity();
        this.appUpdateManager = AppUpdateManagerFactory.create(activity);

        reactContext.addActivityEventListener(new ActivityEventListener() {
            @Override
            public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
                if (requestCode == MY_REQUEST_CODE) {
                    if (resultCode != Activity.RESULT_OK) {
                        checkForUpdates();
                    }
                }
            }

            @Override
            public void onNewIntent(Intent intent) {}
        });
    }

    @Override
    public String getName() {
        return "InAppUpdate";
    }

    @ReactMethod
    public void checkForUpdates(Promise promise) {
        appUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
            if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE &&
                    appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) {
                startUpdateFlow(appUpdateInfo, promise);
            } else {
                promise.resolve("No Update Available");
            }
        }).addOnFailureListener(promise::reject);
    }

    private void startUpdateFlow(AppUpdateInfo appUpdateInfo, Promise promise) {
        try {
            appUpdateManager.startUpdateFlowForResult(
                    appUpdateInfo,
                    AppUpdateType.FLEXIBLE,
                    activity,
                    MY_REQUEST_CODE);
            promise.resolve("Update Started");
        } catch (IntentSender.SendIntentException e) {
            promise.reject("Error", e);
        }
    }

    private void popupSnackBarForCompleteUpdate() {
        appUpdateManager.completeUpdate();
    }

    public void onResume() {
        appUpdateManager.getAppUpdateInfo().addOnSuccessListener(appUpdateInfo -> {
            if (appUpdateInfo.installStatus() == InstallState.DOWNLOADED) {
                popupSnackBarForCompleteUpdate();
            }
        });
    }

    @Override
    public void onCatalystInstanceDestroy() {
        super.onCatalystInstanceDestroy();
        appUpdateManager.unregisterListener(stateUpdatedListener);
    }

    InstallStateUpdatedListener stateUpdatedListener = installState -> {
        if (installState.installStatus() == InstallState.DOWNLOADED) {
            popupSnackBarForCompleteUpdate();
        }
    };
}
        


Step 3: Register the Module

Register the native module to make it available in the React Native application.

  • Open MainApplication.java and modify it as follows:

import com.yourproject.InAppUpdateModule;

public class MainApplication extends Application implements ReactApplication {

    // Other code...

    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new InAppUpdatePackage() // Add this line
        );
    }
}
        

  • Create the Package Class

Create InAppUpdatePackage.java to manage the module's lifecycle:

package com.yourproject;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.Collections;
import java.util.List;

public class InAppUpdatePackage implements ReactPackage {

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }

    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Collections.singletonList(new InAppUpdateModule(reactContext));
    }
}
        

Step 4: Integrate the Module in React Native

Now that we've set up the native module, we can integrate it with the React Native app.

Link the Native Module

  • Use React Native's autolinking to ensure the module is recognized:

cd android
./gradlew clean
cd ..        

  • Use the Module in JavaScript

Create a component in your React Native app to check for updates:

import React, { useEffect } from 'react';
import { NativeModules, Button, View, Text } from 'react-native';

const { InAppUpdate } = NativeModules;

const App = () => {

  useEffect(() => {
    InAppUpdate.checkForUpdates()
      .then((message) => console.log(message))
      .catch((error) => console.error(error));
  }, []);

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Welcome to In-App Update Demo!</Text>
      <Button title="Check for Update" onPress={() => {
        InAppUpdate.checkForUpdates()
          .then((message) => console.log(message))
          .catch((error) => console.error(error));
      }} />
    </View>
  );
};

export default App;
        


Step 5: Handle Update Completion

To ensure updates are completed smoothly, handle post-update actions:

InstallStateUpdatedListener stateUpdatedListener = installState -> {
    if (installState.installStatus() == InstallStatus.DOWNLOADED) {
        popupSnackBarForCompleteUpdate();
    }
};

private void popupSnackBarForCompleteUpdate() {
    Snackbar.make(
            activity.findViewById(android.R.id.content),
            "An update has been downloaded.",
            Snackbar.LENGTH_INDEFINITE
    ).setAction(
            "RESTART", view -> {
                appUpdateManager.completeUpdate();
            }
    ).show();
}
        


Conclusion

Implementing in-app updates in a React Native application provides a seamless and efficient way to deliver the latest features and fixes directly to your users. By bridging native Android capabilities with React Native, you can ensure your app remains current and user-friendly.

Key Takeaways:

  • Seamless Updates: Allow users to download updates without leaving the app.
  • Increased Engagement: Encourage users to explore new features quickly.
  • Enhanced Reliability: Address bugs and issues promptly with direct updates.

By following this guide, you can significantly improve user experience and engagement in your React Native applications.

Additional Resources

  • Testing Updates: Consider using Google Play Console's internal testing tracks to ensure updates are stable before a full rollout.
  • User Notifications: Inform users about available updates and encourage them to stay current.

If you're looking to elevate your app's user experience, implementing in-app updates is a step in the right direction. Feel free to connect if you have any questions or need further assistance in implementing this feature!

To view or add a comment, sign in

More articles by Manav Garg

Others also viewed

Explore content categories