npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-google-play-games

v0.3.0

Published

Android-only React Native TurboModule for Google Play Games Services.

Downloads

437

Readme

react-native-google-play-games

Android-only React Native TurboModule for Google Play Games Services.

This package focuses on Google Play Games single sign-on, achievements, and leaderboards for React Native 0.80+ with the New Architecture only.

Included in v0.4.0

  • isAuthenticated()
  • signIn()
  • signOut()
  • getPlayer()
  • unlockAchievement()
  • incrementAchievement()
  • showAchievements()
  • submitScore()
  • showLeaderboard()
  • showAllLeaderboards()
  • loadCurrentPlayerScore()

Note: Google Play Games Services v2 on Android no longer exposes a native sign-out API. In this library, signOut() is kept in the JS surface for API stability, but currently rejects with E_SIGN_OUT_UNSUPPORTED.

API

export type GooglePlayGamesPlayer = {
  id: string;
  displayName: string;
  title: string | null;
  iconImageUrl: string | null;
  hiResImageUrl: string | null;
};

export type GooglePlayGamesLeaderboardScore = {
  leaderboardId: string;
  rawScore: number;
  formattedScore: string;
  rank: string | null;
  tag: string | null;
};

isAuthenticated(): Promise<boolean>;
signIn(): Promise<GooglePlayGamesPlayer>;
signOut(): Promise<void>;
getPlayer(): Promise<GooglePlayGamesPlayer | null>;
unlockAchievement(achievementId: string): Promise<void>;
incrementAchievement(achievementId: string, steps?: number): Promise<void>;
showAchievements(): Promise<void>;
submitScore(leaderboardId: string, score: number): Promise<void>;
showLeaderboard(leaderboardId: string): Promise<void>;
showAllLeaderboards(): Promise<void>;
loadCurrentPlayerScore(
  leaderboardId: string,
): Promise<GooglePlayGamesLeaderboardScore | null>;

Installation

npm install react-native-google-play-games

This library is Android-only and expects:

  • React Native 0.80+
  • New Architecture enabled
  • An Android app that is already configured for Google Play Games Services

Native Android notes

The library auto-initializes PlayGamesSdk through an Android ContentProvider, so consuming apps do not need to manually call PlayGamesSdk.initialize(...).

The Android namespace used by this library is:

com.reactnativegoogleplaygames

The TurboModule is registered internally as:

GooglePlayGames

Google Play Games setup requirements

For sign-in to succeed, the consuming Android app still needs proper Play Games configuration in Google Play Console and Google Cloud:

  • Your game must be created in Play Console with Play Games Services enabled.
  • The Android package name and SHA-1 certificate fingerprint must match the linked Android credential.
  • If you want Play Games to work on an Android Emulator, add your app's debug keystore SHA-1 to the Android credential in Google Play Console / Google Play Games Services.
  • The Google account used on the device must be a tester for the Play Games project when required.
  • The app must be installed in a way that matches your Play Games configuration.

Without that setup, the module code can be correct and sign-in will still fail.

Required Android APP_ID setup

This package also requires your app's Google Play Games APP_ID to be added to your Android app configuration. Without this, sign-in may fail even when the rest of the Play Games setup looks correct.

Add this to your app's AndroidManifest.xml inside the <application> tag:

<meta-data
  android:name="com.google.android.gms.games.APP_ID"
  android:value="@string/app_id" />

Then define the value in android/app/src/main/res/values/strings.xml:

<string name="app_id">4xxxxxxxxxxx</string>

You can find this APP_ID after connecting your game to a Google Cloud project:

Google Play Console -> Select your game -> Grow Users -> Play Games Services -> Setup and management -> Configuration

Emulator and debug keystore note

If you're testing on an emulator or a debug build, make sure the SHA-1 from your debug keystore is added to the Android credential used by Google Play Games Services. In practice, this is often the missing step when Play Games works in production configuration but not in local development.

The Android credential can be found in Google Play Console under your Play Games Services configuration. If the package name matches but the SHA-1 does not, authentication will still fail.

Usage

import GooglePlayGames from 'react-native-google-play-games';

export async function ensurePlayGamesPlayer() {
  const alreadyAuthenticated = await GooglePlayGames.isAuthenticated();

  if (!alreadyAuthenticated) {
    return GooglePlayGames.signIn();
  }

  const player = await GooglePlayGames.getPlayer();

  if (!player) {
    throw new Error('Player was not available after authentication.');
  }

  return player;
}

Achievements usage

import GooglePlayGames from 'react-native-google-play-games';

export async function unlockFirstWin() {
  await GooglePlayGames.unlockAchievement('CgkIxxxxxxxxEAIQAQ');
}

export async function addProgress() {
  await GooglePlayGames.incrementAchievement('CgkIxxxxxxxxEAIQAg', 1);
}

export async function openAchievementsScreen() {
  await GooglePlayGames.showAchievements();
}

Achievements setup requirements

  • Define your achievements in Google Play Console before calling these APIs.
  • Use the Play Games achievement IDs from your Console configuration.
  • incrementAchievement() should only be used with incremental achievements.
  • showAchievements() opens the native Google Play Games achievements UI.

Leaderboards usage

import GooglePlayGames from 'react-native-google-play-games';

export async function submitBestScore(score: number) {
  await GooglePlayGames.submitScore('CgkIxxxxxxxxEAIQAw', score);
}

export async function openLeaderboard() {
  await GooglePlayGames.showLeaderboard('CgkIxxxxxxxxEAIQAw');
}

export async function openAllLeaderboards() {
  await GooglePlayGames.showAllLeaderboards();
}

export async function getCurrentScore() {
  return GooglePlayGames.loadCurrentPlayerScore('CgkIxxxxxxxxEAIQAw');
}

Leaderboards setup requirements

  • Define your leaderboards in Google Play Console before calling these APIs.
  • Use the Play Games leaderboard IDs from your Console configuration.
  • submitScore() expects a whole-number raw score value.
  • showLeaderboard() opens the native Google Play Games leaderboard UI for the provided leaderboard.
  • showAllLeaderboards() opens the native list of all Play Games leaderboards for your game.
  • loadCurrentPlayerScore() returns the signed-in player's public all-time score for that leaderboard, or null if no score exists yet.

Example: PlayGamesContext.tsx

If you want to keep Play Games auth state available across your app, you can wrap the module in a React context like this:

import React, {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react';
import {Platform} from 'react-native';
import GooglePlayGames, {
  type GooglePlayGamesPlayer,
} from 'react-native-google-play-games';

type PlayGamesContextType = {
  isSupported: boolean;
  isInitializing: boolean;
  isAuthenticated: boolean;
  player: GooglePlayGamesPlayer | null;
  error: string | null;
  refreshSession: () => Promise<void>;
  signIn: () => Promise<GooglePlayGamesPlayer | null>;
  signOut: () => Promise<void>;
};

const PlayGamesContext = createContext<PlayGamesContextType | undefined>(
  undefined,
);

export const PlayGamesProvider: React.FC<{children: React.ReactNode}> = ({
  children,
}) => {
  const isSupported = Platform.OS === 'android';
  const [isInitializing, setIsInitializing] = useState(isSupported);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [player, setPlayer] = useState<GooglePlayGamesPlayer | null>(null);
  const [error, setError] = useState<string | null>(null);

  const refreshSession = useCallback(async () => {
    if (!isSupported) {
      setIsInitializing(false);
      setIsAuthenticated(false);
      setPlayer(null);
      setError(null);
      return;
    }

    try {
      setError(null);
      const authenticated = await GooglePlayGames.isAuthenticated();
      setIsAuthenticated(authenticated);

      if (!authenticated) {
        setPlayer(null);
        return;
      }

      const currentPlayer = await GooglePlayGames.getPlayer();
      setPlayer(currentPlayer);
    } catch (sessionError) {
      console.log('Failed to refresh Google Play Games session:', sessionError);
      setIsAuthenticated(false);
      setPlayer(null);
      setError(
        sessionError instanceof Error
          ? sessionError.message
          : 'Failed to refresh Play Games session.',
      );
    } finally {
      setIsInitializing(false);
    }
  }, [isSupported]);

  useEffect(() => {
    refreshSession();
  }, [refreshSession]);

  const signIn = useCallback(async () => {
    if (!isSupported) {
      return null;
    }

    try {
      setError(null);
      const signedInPlayer = await GooglePlayGames.signIn();
      setPlayer(signedInPlayer);
      setIsAuthenticated(true);
      return signedInPlayer;
    } catch (signInError) {
      console.log('Google Play Games sign-in failed:', signInError);
      setIsAuthenticated(false);
      setPlayer(null);
      setError(
        signInError instanceof Error
          ? signInError.message
          : 'Google Play Games sign-in failed.',
      );
      return null;
    }
  }, [isSupported]);

  const signOut = useCallback(async () => {
    if (!isSupported) {
      return;
    }

    try {
      setError(null);
      await GooglePlayGames.signOut();
      setIsAuthenticated(false);
      setPlayer(null);
    } catch (signOutError) {
      console.log('Google Play Games sign-out failed:', signOutError);
      setError(
        signOutError instanceof Error
          ? signOutError.message
          : 'Google Play Games sign-out failed.',
      );
    }
  }, [isSupported]);

  const value = useMemo(
    () => ({
      isSupported,
      isInitializing,
      isAuthenticated,
      player,
      error,
      refreshSession,
      signIn,
      signOut,
    }),
    [
      error,
      isAuthenticated,
      isInitializing,
      isSupported,
      player,
      refreshSession,
      signIn,
      signOut,
    ],
  );

  return (
    <PlayGamesContext.Provider value={value}>
      {children}
    </PlayGamesContext.Provider>
  );
};

export const usePlayGames = () => {
  const context = useContext(PlayGamesContext);

  if (!context) {
    throw new Error('usePlayGames must be used within a PlayGamesProvider');
  }

  return context;
};

Wrap your app with the provider:

<PlayGamesProvider>
  <YourApp />
</PlayGamesProvider>

Status

Planned next for this package:

  • Achievements APIs