Skip to main content

games_services_watchos 0.2.0 copy "games_services_watchos: ^0.2.0" to clipboard
games_services_watchos: ^0.2.0 copied to clipboard

watchOS implementation of the games_services plugin: Game Center leaderboards over GameKit, bridged with dart:ffi.

example/lib/main.dart

// Copyright 2026 The FlutterWatch Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show PlatformException;
import 'package:flutter_watchos/flutter_watchos.dart';
import 'package:games_services/games_services.dart';

/// Replace with a leaderboard id from your own App Store Connect record; a
/// simulator has no Game Center account, so the interesting states here are
/// the failures, and they are the point of the example.
const String kLeaderboardId = 'your.leaderboard.id';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) =>
      const MaterialApp(home: Scaffold(body: _Body()));
}

class _Body extends StatefulWidget {
  const _Body();

  @override
  State<_Body> createState() => _BodyState();
}

class _BodyState extends State<_Body> {
  final List<String> _log = <String>[];

  void _say(String line) => setState(() => _log.insert(0, line));

  // As on iOS with games_services 5.x, signIn and submitScore complete with
  // a message on success and throw a PlatformException on failure.
  Future<void> _signIn() async {
    try {
      _say(await GameAuth.signIn() ?? 'signed in');
    } on PlatformException catch (e) {
      _say('sign-in failed: ${e.message}');
    }
  }

  Future<void> _submit() async {
    try {
      await GamesServices.submitScore(
        score: Score(iOSLeaderboardID: kLeaderboardId, value: 10),
      );
      _say('submitted 10');
    } on PlatformException catch (e) {
      _say('submit failed: ${e.message}');
    }
  }

  Future<void> _load() async {
    final List<LeaderboardScoreData>? rows =
        await Leaderboards.loadLeaderboardScores(
      iOSLeaderboardID: kLeaderboardId,
      scope: PlayerScope.global,
      timeScope: TimeScope.allTime,
      maxResults: 5,
    );
    // Null and empty mean different things, and the example says which.
    if (rows == null) {
      _say('load failed');
    } else if (rows.isEmpty) {
      _say('no scores');
    } else {
      _say(rows.map((r) => '${r.rank}. ${r.displayScore}').join('  '));
    }
  }

  @override
  Widget build(BuildContext context) {
    return ListView(
      // No SafeArea, so the list fills the screen the way a native watchOS
      // list does: rows scroll under the clock and down to the bottom edge.
      // The insets go into the list's padding instead. The default safe area
      // leaves the clock out of MediaQuery's padding, so the top comes from
      // WatchStatusBar.heightOf, the clock's band, in either safe area; the
      // other sides take MediaQuery's insets, so the rows stay clear of the
      // rounded corners and the last one scrolls clear of the bottom edge.
      padding: MediaQuery.paddingOf(context)
              .copyWith(top: WatchStatusBar.heightOf(context)) +
          const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
      children: <Widget>[
        // GameAuth.player gives the current sign-in state at once, and a new
        // one when a call changes it.
        StreamBuilder<PlayerData?>(
          stream: GameAuth.player,
          builder: (BuildContext context, AsyncSnapshot<PlayerData?> player) {
            final String? name = player.data?.displayName;
            return Text(
              name == null ? 'signed out' : 'signed in as $name',
              style: const TextStyle(fontSize: 12),
            );
          },
        ),
        TextButton(onPressed: _signIn, child: const Text('Sign in')),
        TextButton(onPressed: _submit, child: const Text('Submit 10')),
        TextButton(onPressed: _load, child: const Text('Load scores')),
        for (final String line in _log)
          Text(line, style: const TextStyle(fontSize: 11)),
      ],
    );
  }
}
0
likes
140
points
295
downloads

Documentation

API reference

Publisher

verified publisherflutterwatch.dev

Weekly Downloads

watchOS implementation of the games_services plugin: Game Center leaderboards over GameKit, bridged with dart:ffi.

Homepage
Repository (GitHub)
View/report issues

Topics

#watchos #ffi #games-services #game-center

License

BSD-3-Clause (license)

Dependencies

ffi, flutter, games_services_platform_interface

More

Packages that depend on games_services_watchos

Packages that implement games_services_watchos