androidreact-nativeexpoin-app-update

Getting Error: sp-react-native-in-app-updates checkNeedsUpdate (In App Update Feature)


I am trying to add in app update feature into my app. I setup everything according to the documentation

Getting this error on my physical device (Android): [Error: sp-react-native-in-app-updates checkNeedsUpdate error: Error: com.google.android.play.core.install.InstallException: -10: Install Error(-10): The app is not owned by any user on this device. An app is "owned" if it has been acquired from Play. (https://developer.android.com/reference/com/google/android/play/core/install/model/InstallErrorCode#ERROR_APP_NOT_OWNED)]

Getting this error on emulator (Android): [Error: sp-react-native-in-app-updates checkNeedsUpdate error: Error: com.google.android.play.core.install.InstallException: -6: Install Error(-6): The download/install is not allowed, due to the current device state (e.g. low battery, low disk space, ...). (https://developer.android.com/reference/com/google/android/play/core/install/model/InstallErrorCode#ERROR_INSTALL_NOT_ALLOWED)]

babel.config.js

module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: [
      [
        'module-resolver',
        {
          root: ['.'],
          alias: {
            'react-native-device-info': './react-native-device-info.js'
          }
        }
      ],
      'nativewind/babel',
      'react-native-reanimated/plugin'],
    env: {
      production: {
        plugins: ['react-native-paper/babel'],
      },
    },
  };
};

react-native-device-info.js

import Constants from "expo-constants"

export const getBundleId = () => {
    return Constants.expoConfig?.ios?.bundleIdentifier ?? '';
}
export const getVersion = () => {
    return Constants.expoConfig?.version
}
export default {
    getBundleId,
    getVersion,
};

checkAppUpdate.ts

import SpInAppUpdates, {
    IAUUpdateKind,
    StartUpdateOptions,
    IAUInstallStatus,
  } from "sp-react-native-in-app-updates";
  import { Platform } from "react-native";
  
  export const checkForUpdate = async () => {
    const inAppUpdates = new SpInAppUpdates(
      false// isDebug
    );
    // curVersion is optional if you don't provide it will automatically take from the app using react-native-device-info
    try {
      console.log("checking for update");
      await inAppUpdates.checkNeedsUpdate().then((result) => {
        console.log("result", result);
        try {
          if (result.shouldUpdate) {
            let updateOptions: StartUpdateOptions = {};
            if (Platform.OS === "android") {
              // android only, on iOS the user will be promped to go to your app store page
              updateOptions = {
                updateType: IAUUpdateKind.IMMEDIATE,
              };
            }
            if (Platform.OS === "ios") {
              updateOptions = {
                title: "Update available",
                message:
                  "There is a new version of the app available on the App Store, do you want to update it?",
                buttonUpgradeText: "Update",
                buttonCancelText: "Cancel",
              };
            }
            inAppUpdates.addStatusUpdateListener((downloadStatus) => {
              console.log("download status", downloadStatus);
              if (downloadStatus.status === IAUInstallStatus.DOWNLOADED) {
                console.log("downloaded");
                inAppUpdates.installUpdate();
                inAppUpdates.removeStatusUpdateListener((finalStatus) => {
                  console.log("final status", finalStatus);
                });
              }
            });
            inAppUpdates.startUpdate(updateOptions);
          }
        } catch (error) {
          console.log("nested error", error);
        }
      });
    } catch (error) {
      console.log("error", error);
    }
  };

Can anyone help me with proper implementation guidelines? Thank you

I am trying to add an in-app update option so that users can update my app through the app (auto popup).


Solution

  • As a prerequisite

    To test the in-app update functionality you must distribute the application through the internal testing track on Google play store first.


    Now let's discuss about the error message

    "com.google.android.play.core.install.InstallException: -10: Install Error(-10): The app is not owned by any user on this device."

    Indicates that the app you are trying to update is not installed on the device. This means that the app has not been acquired from the Google Play Store, and therefore the device does not have the necessary permissions to update it.

    To fix this issue, you will have to add check in your code.

    try {
        getPackageManager().getPackageInfo("com.example.app", PackageManager.GET_ACTIVITIES);
    } catch (PackageManager.NameNotFoundException e) {
      // App is not installed
    }
    

    If the app is not installed, you can trigger intent to Google play for the user to install the app using the following code:

    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=com.example.app"));
    startActivity(intent);
    

    Apk installer intent :

    Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE);
    intent.setData(Uri.parse("file:///path/to/app.apk"));
    startActivity(intent);
    

    Note:

    This is native code you can use it by creating javascript interface and call it from your react native code.

    Reference link:

    https://developer.android.com/reference/com/google/android/play/core/install/model/InstallErrorCode#ERROR_APP_NOT_OWNED