Créer une application de partage de photos avec Google Photos et Flutter

Objectif de cet atelier

Dans cet atelier de programmation, vous allez créer une application de sortie scolaire appelée Field Trippa, permettant aux utilisateurs de partager des photos.

Découvrez comment utiliser l'API Library de Google Photos pour optimiser un environnement de partage de médias dans votre propre application.

L'application utilisée dans cet atelier de programmation a été conçue à l'aide de Flutter, le kit d'interface utilisateur de Google qui permet de développer de superbes applications compilées de manière native pour les mobiles, le Web et les ordinateurs de bureau à partir d'un codebase unique. Pour en savoir plus, rendez-vous sur https://flutter.dev.

5757e359f222ccf6.png

Points abordés

  • Comment utiliser l'API Library de Google Photos pour importer du contenu multimédia et partager des albums
  • Comment utiliser Google Sign-In dans Flutter
  • Comment effectuer des appels d'API Google à partir de Flutter

Prérequis

  • Environnement de développement Flutter
  • Deux comptes utilisateur Google configurés sur différents émulateurs ou appareils ayant accès à Google Photos, afin que vous puissiez tester le partage entre les utilisateurs
  • Un appareil Android, un émulateur ou un appareil iOS physique : le simulateur iOS n'est pas pris en charge en raison de l'absence de caméra

Dans cet atelier de programmation, vous allez créer une application permettant de partager les photos prises lors d'une excursion ou d'un voyage scolaire, à l'aide de l'API Library de Google Photos.

L'utilisateur se connecte à l'aide de Google Sign-in et autorise l'application à utiliser l'API Library de Google Photos.

Il pourra ensuite créer un trip pour importer des photos accompagnées d'une description. Chaque trip peut être partagé avec d'autres utilisateurs de l'application, qui peuvent également ajouter des photos.

146953eced1f4f92.png

En arrière-plan, chaque trip est stocké en tant qu'album partagé dans Google Photos. L'application gère le partage et l'importation de contenu dans cet album. Cependant, vous pouvez également partager l'album avec des personnes qui ne disposent pas de l'application à l'aide d'une URL pointant vers Google Photos.

c4af82aa4bf8cc31.png

Qu'attendez-vous de cet atelier de programmation ?

Je suis novice en la matière et je voudrais avoir un bon aperçu. Je connais un peu le sujet, mais j'aimerais revoir certains points. Je recherche un exemple de code à utiliser dans mon projet. Je cherche des explications sur un point spécifique.

b2f84ff91b0e1396.pngTélécharger le code source de cet atelier de programmation :

Télécharger le code source Parcourir sur GitHub

(Le code de démarrage de l'application est disponible dans la branche main du dépôt.)

Décompressez le fichier ZIP téléchargé. Cette opération crée un dossier racine, photos-sharing-main, contenant l'ensemble du code et des ressources nécessaires pour commencer.

Ouvrez le dossier extrait dans l'IDE Flutter de votre choix (VSCode ou Android Studio, par exemple) avec les plug-ins Dart et Flutter installés.

Code d'implémentation final

Le lien suivant pointe vers la version finale de l'application entièrement implémentée. Vous pouvez utiliser ce qui suit si vous êtes bloqué ou si vous souhaitez comparer votre implémentation :

Télécharger le code source final Parcourir le code source final sur GitHub

(Le code d'application final est disponible dans la branche final du dépôt.)

Si vous n'avez pas encore développé votre solution avec Flutter, suivez ces étapes pour configurer votre environnement de développement.

Pour exécuter l'application Field Trippa, cliquez sur le bouton "run" (Exécuter) dans votre IDE de développement ou utilisez la commande suivante à partir du répertoire racine du code source :

flutter run

L'écran Connect with Google Photos (Se connecter avec Google Photos) doit normalement s'afficher :

6bfc7e3fab746b8d.png

L'API Library de Google Photos nécessite l'authentification de vos utilisateurs à l'aide du protocole OAuth 2.0. Les utilisateurs se connectent à l'application et l'autorisent à interagir avec l'API en leur nom.

Vous trouverez d'autres conseils de dépannage à la fin de cette étape.

Créer un projet Firebase et enregistrer votre application

b2f84ff91b0e1396.png Accédez à la console Firebase, puis sélectionnez + Add Project (+ Ajouter un projet). Saisissez un nom de projet, puis sélectionnez Create Project (Créer un projet) pour continuer. Ignorez toutes les autres étapes de la console Firebase. Revenez plutôt à cet atelier de programmation et passez aux sections "Android" ou "iOS" ci-dessous pour configurer l'application.

Android uniquement – Si vous exécutez l'application sur Android, enregistrez une application Android :

b2f84ff91b0e1396.png Cliquez sur l'icône Android pour ouvrir l'écran d'enregistrement de l'application Android.

b2f84ff91b0e1396.png Dans package, saisissez : com.google.codelab.photos.sharing

b2f84ff91b0e1396.pngRécupérez le certificat de signature SHA-1 à partir de votre ordinateur :

Sous Windows, exécutez la commande suivante :

keytool -alias androiddebugkey -keystore %USERPROFILE%\.android\debug.keystore -list -v -storepass android

Sous Mac ou Linux, exécutez la commande suivante :

keytool -alias androiddebugkey -keystore ~/.android/debug.keystore -list -v -storepass android

b2f84ff91b0e1396.png Cliquez sur register app (Enregistrer l'application) pour continuer.

b2f84ff91b0e1396.png Téléchargez le fichier google-service.json sur votre ordinateur et déplacez-le dans le répertoire "android/app/". Astuce : dans Android Studio, vous pouvez faire glisser le fichier téléchargé directement à l'emplacement approprié dans le panneau latéral project.

Ce fichier contient la configuration du projet Firebase et Google Developers que vous venez de configurer.

Pour en savoir plus, consultez la documentation sur le package google_sign_in.

Aucune autre opération n'est obligatoire dans la console Firebase. Le SDK Firebase a déjà été ajouté à l'application.

iOS uniquement – Si vous exécutez l'application sur iOS, enregistrez une application iOS dans Firebase :

b2f84ff91b0e1396.png Cliquez sur l'icône iOS pour ouvrir l'écran d'enregistrement de l'application iOS.

b2f84ff91b0e1396.png Dans iOS bundle ID (ID de groupe iOS), saisissez : com.google.codelab.photos.sharing

b2f84ff91b0e1396.png Cliquez sur Next (Suivant) pour continuer.

b2f84ff91b0e1396.png Téléchargez le fichier GoogleService-Info.plist sur votre ordinateur.

b2f84ff91b0e1396.png Ouvrir le projet Flutter dans Xcode

b2f84ff91b0e1396.png Effectuez un clic droit sur le répertoire Runner, sélectionnez Add Files to Runner (Ajoutez les fichiers à Runner), puis sélectionnez le fichier GoogleService-Info.plist que vous avez téléchargé afin de l'ajouter au module Runner.

b2f84ff91b0e1396.png Modifiez le code source du fichier ios/Runner/Info.plist et ajoutez la valeur de la propriété REVERSED_CLIENT_ID à partir du fichier GoogleService-Info.plist. Remplacez l'entrée qui figure au bas du fichier :

ios/Runner/Info.plist

<!-- Google Sign-in Section -->
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>COPY_REVERSED_CLIENT_ID_HERE</string>
    </array>
  </dict>
</array>
<!-- End of the Google Sign-in Section -->

Pour en savoir plus, consultez la documentation sur le package google_sign_in.

Activer l'API Library de Google Photos

b2f84ff91b0e1396.png Ouvrez l'écran de l'API dans Google Developers Console et activez l'API Library de Google Photos. Si le bouton enable (Activer) est désactivé, vous devrez peut-être sélectionner d'abord le projet Firebase en haut de l'écran.

b2f84ff91b0e1396.png Ouvrez la configuration de l'écran d'autorisation OAuth dans Google Developers Console pour ajouter les champs d'application de l'API Library de Google Photos et votre adresse e-mail. (Cette configuration est requise pour la vérification du protocole OAuth pour tous les champs d'application utilisés par l'API Library de Google Photos.) Vous ne devez pas envoyer de demande de validation, mais vous devez remplir le formulaire et enregistrer votre réponse. Les champs d'application seront alors activés pour le développement et pour les tests.

  • Saisissez le nom de l'application. Par exemple : Field Trippa Codelab
  • Sélectionnez une adresse e-mail d'assistance.
  • Sélectionnez Add scope (Ajouter un champ d'application), puis manually add paste scopes (coller manuellement les champs d'application) pour saisir les champs d'application suivants :
https://www.googleapis.com/auth/photoslibrary
https://www.googleapis.com/auth/photoslibrary.sharing
  • Sélectionnez Save (Enregistrer).
  • Il n'est pas nécessaire d'envoyer une demande de validation pour poursuivre cet atelier de programmation. Cette étape n'est obligatoire que lors du lancement de votre application, et non pour les tests personnels.

Exécuter l'application et se connecter

Google Sign-In a déjà été implémenté à l'aide du package google_sign_in flutter. Ce package nécessite les fichiers google-services.json ou GoogleService-Info.plist que vous avez déjà copiés dans le projet.

b2f84ff91b0e1396.png Exécutez à nouveau l'application et sélectionnez Connect to Google Photos (Se connecter à Google Photos). Vous êtes invité à sélectionner un compte utilisateur et à accepter les niveaux d'authentification.

Une fois tous les éléments configurés, une liste vide s'affiche sur l'écran suivant.

9f3bcae1f8e7cd0d.png

Résoudre les problèmes de connexion

Si vous ne parvenez pas à vous connecter à l'application, vérifiez les points ci-dessous :

b2f84ff91b0e1396.png Vérifiez que l'appareil est connecté à Internet.

b2f84ff91b0e1396.png Si le message d'erreur PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null) s'affiche, assurez-vous que vous avez suivi toutes les étapes de la section Activer l'API Library de Google Photos. Vous devez ajouter les champs d'application de l'API Library de Google Photos, saisir une adresse e-mail d'assistance, puis sélectionner save (Enregistrer).

b2f84ff91b0e1396.png Si le message d'erreur r PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 12500: , null) s'affiche, vérifiez que vous avez ajouté une adresse e-mail d'assistance dans la console Firebase. Ouvrez la console Firebase et accédez aux paramètres du projet en sélectionnant l'icône en forme de roue dentée à côté du titre de votre projet. Sélectionnez une adresse e-mail sous support email (Adresse e-mail d'assistance) sur l'écran general settings (Paramètres généraux).

b2f84ff91b0e1396.png Vérifiez le certificat de signature SHA-1 configuré dans la console Firebase. Correspond-il au résultat de la commande keytool obtenu à la première étape ? Correspond-il au résultat de la commande ./gradlew signingReport en cas d'exécution dans le projet android/ ? Il se peut que vous deviez également inclure le certificat de signature SHA-256 dans la console.

b2f84ff91b0e1396.png Vérifiez le nom du package et l'ID de groupe iOS configurés dans les champs correspondants de la console Firebase. Cette valeur doit être définie sur com.google.codelab.photos.sharing.

b2f84ff91b0e1396.png Vérifiez l'emplacement des fichiers de configuration que vous avez téléchargés à partir de la console Firebase. Pour Android, le fichier doit être copié dans android/app/google-service.json. Pour iOS, vous devez l'ajouter au module Runner.

b2f84ff91b0e1396.png Vous devrez peut-être activer Google comme fournisseur de connexion pour votre projet Firebase. Ouvrez la console Firebase, puis accédez à Authentification et à Méthode de connexion. Assurez-vous que Google est bien activé.

Avant d'implémenter le premier appel d'API sur l'API Library de Google Photos, examinons l'architecture de données utilisée par l'application Field Trippa.

Architecture de l'application

  • Chaque écran est implémenté sous la forme d'une page distincte : 71b9a588fb1bbb41.png
  • Le fichier PhotosLibraryApiModel décrit le modèle de données de l'application et fait abstraction des appels de l'API Library de Google Photos.
  • Les appels REST HTTPS vers l'API Library sont implémentés dans PhotosLibraryApiClient. Chaque appel fourni par cette classe utilise un objet *Request dans lequel vous spécifiez des paramètres et des options.
  • L'API Library nécessite l'authentification des utilisateurs via OAuth2. Le jeton d'accès qui doit être inclus dans tous les appels d'API est défini directement par le package google_sign_in sur PhotosLibraryApiClient.

Implémenter l'appel d'API de création d'albums

Chaque voyage est stocké sous la forme d'un album dans Google Photos. Lorsque vous sélectionnez le bouton CREATE A TRIP ALBUM (CRÉER UN ALBUM DE VOYAGE), vous devez demander à l'utilisateur le nom du voyage et créer un album ayant ce nom comme titre.

b2f84ff91b0e1396.png Dans create_trip_page.dart, écrivez la logique qui envoie une requête à l'API Library pour créer l'album. Implémentez la méthode _createTrip(...) à la fin du fichier pour appeler la classe PhotosLibraryApiModel avec le nom du voyage saisi par l'utilisateur.

lib/pages/create_trip_page.dart

Future<void> _createTrip(BuildContext context) async {
  // Display the loading indicator.
  setState(() => _isLoading = true);

  await ScopedModel.of<PhotosLibraryApiModel>(context)
      .createAlbum(tripNameFormController.text);

  // Hide the loading indicator.
  setState(() => _isLoading = false);
  Navigator.pop(context);
}

b2f84ff91b0e1396.png Implémentez l'appel vers l'API Library qui crée l'album. Dans le modèle d'API, implémentez la méthode createAlbum(...) qui utilise le titre de l'album en tant que paramètre. Un appel est alors effectué vers la PhotosLibraryApiClient où est exécuté l'appel REST proprement dit.

lib/model/photos_library_api_model.dart

Future<Album> createAlbum(String title) async {
  final album = await client.createAlbum(CreateAlbumRequest.fromTitle(title));
  updateAlbums();
  return album;
}

b2f84ff91b0e1396.png Implémentez l'appel REST pour créer l'album dans photos_library_api_client.dart. Pour rappel, CreateAlbumRequest contient déjà la propriété title requise pour cet appel.

Le code suivant l'encode au format JSON et ajoute les en-têtes d'authentification pour autoriser la requête. Pour terminer, renvoyez l'album créé par l'API.

lib/photos_library_api/photos_library_api_client.dart

Future<Album> createAlbum(CreateAlbumRequest request) async {
  final response = await http.post(
    Uri.parse('https://photoslibrary.googleapis.com/v1/albums'),
    body: jsonEncode(request),
    headers: await _authHeaders,
  );

  printError(response);

  return Album.fromJson(jsonDecode(response.body));
}

Faites un essai !

b2f84ff91b0e1396.png Déployez l'application, puis sélectionnez + Create Trip (+ Créer un voyage).

2f0bec785bec1710.gif

Vous avez peut-être remarqué que la liste de voyages contenait d'autres albums Google Photos qui n'avaient pas été créés par votre application. Si vous ne possédez aucun autre album dans Google Photos et que vous souhaitez voir comment cela se passe, ouvrez l'application Google Photos et créez un album. Sachez toutefois que cela n'est pas obligatoire pour poursuivre cet atelier de programmation.

N'oubliez pas que chaque voyage est stocké sous la forme d'un album dans Google Photos. Cependant, il ne serait pas logique d'afficher d'autres albums Google Photos créés par d'autres moyens. Field Trippa ne doit afficher que les voyages créés par l'application.

Vous pouvez utiliser l'API pour limiter la liste des voyages proposés afin de n'afficher que ceux qui ont été créés par l'application.

b2f84ff91b0e1396.png Modifiez la méthode listAlbums() (et NON listSharedAlbums()) dans photos_library_api_client.dart. Cette méthode effectue l'appel REST afin de récupérer une liste d'albums. Ajoutez le paramètre excludeNonAppCreatedData=true qui limite les données renvoyées pour exclure les albums qui n'ont pas été créés par cette application.

lib/photos_library_api/photos_library_api_client.dart

Future<ListAlbumsResponse> listAlbums() async {
  final response = await http.get(
        Uri.parse('https://photoslibrary.googleapis.com/v1/albums?'
            'pageSize=50&excludeNonAppCreatedData=true'),
        headers: await _authHeaders);

       ...
}

Faites un essai !

Désormais, la première page n'affiche que les voyages créés par l'application.

c7c20b76dcbfbfea.png

L'étape suivante consiste à importer des photos dans un voyage. Les données étant stockées dans le compte Google Photos de votre utilisateur, vous n'avez pas à vous soucier de l'espace de stockage ni du traitement des données.

Prendre une photo dans Flutter

b2f84ff91b0e1396.png Commencez par implémenter la méthode _getImage(...) dans la boîte de dialogue d'ajout de photos. Cette méthode est appelée lorsque l'utilisateur clique sur le bouton +ADD PHOTO (+ AJOUTER UNE PHOTO).

Le code suivant utilise le package image_picker pour prendre une photo, mettre à jour l'interface utilisateur et appeler le modèle d'API pour importer l'image. (Vous l'implémenterez à l'étape suivante.) L'appel _getImage(...) stocke un jeton d'importation qui sera nécessaire ultérieurement pour créer la photo dans Google Photos.

lib/components/contribute_photo_dialog.dart

Future _getImage(BuildContext context) async {
  // Use the image_picker package to prompt the user for a photo from their
  // device.
  final pickedImage = await _imagePicker
      .getImage(
        source: ImageSource.camera,
      );
  final pickedFile = File(pickedImage.path);

  // Store the image that was selected.
  setState(() {
    _image = pickedFile;
    _isUploading = true;
  });

  // Make a request to upload the image to Google Photos once it was selected.
  final uploadToken = await ScopedModel.of<PhotosLibraryApiModel>(context)
      .uploadMediaItem(pickedFile);

  setState(() {
    // Once the upload process has completed, store the upload token.
    // This token is used together with the description to create the media
    // item later.
    _uploadToken = uploadToken;
    _isUploading = false;
  });
}

Implémenter un appel de l'API Library pour importer l'image afin d'obtenir un jeton d'importation

L'importation de photos et de vidéos dans l'API Library s'effectue en deux étapes :

  1. Importer les octets de contenu multimédia pour recevoir un jeton d'importation
  2. Créer un élément multimédia dans la bibliothèque de l'utilisateur à partir du jeton d'importation

b2f84ff91b0e1396.png Implémentez la requête REST pour importer le contenu multimédia. Vous devez définir des en-têtes pour spécifier le type de requête d'importation, ainsi que le nom du fichier. Dans le fichier photos_library_api_client.dart, implémentez la méthode uploadMediaItem(...) où le fichier est importé, en renvoyant le jeton d'importation de l'appel HTTP :

lib/photos_library_api/photos_library_api_client.dart

Future<String> uploadMediaItem(File image) async {
  // Get the filename of the image
  final filename = path.basename(image.path);

  // Set up the headers required for this request.
  final headers = <String, String>{};
  headers.addAll(await _authHeaders);
  headers['Content-type'] = 'application/octet-stream';
  headers['X-Goog-Upload-Protocol'] = 'raw';
  headers['X-Goog-Upload-File-Name'] = filename;

  // Make the HTTP request to upload the image. The file is sent in the body.
  final response = await http.post(
    Uri.parse('https://photoslibrary.googleapis.com/v1/uploads'),
    body: image.readAsBytesSync(),
    headers: await _authHeaders,
  );

  printError(response);

  return response.body;
}

Créer un élément multimédia à partir d'un jeton d'importation

Ensuite, implémentez la création d'un élément multimédia dans la bibliothèque de l'utilisateur à partir du jeton d'importation.

La création d'un élément multimédia nécessite le jeton d'importation, une description facultative (la légende de la photo ou de la vidéo, par exemple) et l'identifiant facultatif d'un album. Field Trippa ajoute toujours la photo importée directement dans un album de voyages.

b2f84ff91b0e1396.png Implémentez l'appel vers la méthode photos_library_api_client qui appelle mediaItems.batchCreate avec le jeton d'importation, la description et l'ID de l'album. Dans le modèle d'API, implémentez la méthode createMediaItem(...) qui appelle l'API Library. Cette méthode renvoie un élément multimédia.

(Le photos_library_client de cet appel est déjà implémenté.)

lib/model/photos_library_api_model.dart

Future<BatchCreateMediaItemsResponse> createMediaItem(
    String uploadToken, String albumId, String description) async {
  // Construct the request with the token, albumId and description.
  final request =
      BatchCreateMediaItemsRequest.inAlbum(uploadToken, albumId, description);

  // Make the API call to create the media item. The response contains a
  // media item.
  final response = await client.batchCreateMediaItems(request);

  // Print and return the response.
  print(response.newMediaItemResults[0].toJson());
  return response;
}

Faites un essai !

b2f84ff91b0e1396.pngOuvrez l'application et sélectionnez un voyage. Cliquez sur contribute (Contribuer) et sélectionnez une photo que vous avez prise précédemment. Saisissez une description, puis sélectionnez upload (Importer). L'image doit apparaître dans l'album du voyage au bout de quelques secondes.

b2f84ff91b0e1396.png Ouvrez l'album dans l'application Google Photos. La nouvelle image s'affiche dans l'album correspondant à ce voyage.

526ede994fcd5d8d.gif

Jusqu'à présent, vous avez implémenté la fonctionnalité permettant de créer un voyage et avez importé des photos accompagnées d'une description. Dans le backend, chaque voyage est stocké sous la forme d'un album dans Google Photos.

Ensuite, vous partagerez un voyage avec d'autres personnes qui n'utilisent pas votre application.

Chaque voyage est associé à un album dans Google Photos. Vous pouvez donc "partager" un album via une URL et le mettre à la disposition de toute personne disposant de cette URL.

Implémenter l'appel de partage d'un album

Les albums sont partagés à partir de la page correspondant au voyage lorsqu'un utilisateur clique sur un bouton share (Partager) en haut d'un album.

b2f84ff91b0e1396.png Implémentez l'appel asynchrone _shareAlbum(...) qui appelle le modèle de partage de l'album, puis recharge l'album affiché. Le fait de recharger l'album entraîne la propagation de la propriété shareInfo. Elle contient le shareableUrl que vous présenterez ultérieurement à l'utilisateur dans une boîte de dialogue.

lib/pages/trip_page.dart

Future<void> _shareAlbum(BuildContext context) async {
  // Show the loading indicator
  setState(() => _inSharingApiCall = true);

  const snackBar = SnackBar(
    duration: Duration(seconds: 3),
    content: Text('Sharing Album...'),
  );
  Scaffold.of(context).showSnackBar(snackBar);

  // Share the album and update the local model
  await ScopedModel.of<PhotosLibraryApiModel>(context).shareAlbum(album.id);
  final updatedAlbum =
      await ScopedModel.of<PhotosLibraryApiModel>(context).getAlbum(album.id);

  print('Album has been shared.');
  setState(() {
    album = updatedAlbum;
    // Hide the loading indicator
    _inSharingApiCall = false;
  });
}

b2f84ff91b0e1396.png Implémentez la méthode _showShareableUrl(...) qui est appelée lorsque l'utilisateur clique sur le bouton SHARE WITH ANYONE (PARTAGER AVEC TOUT LE MONDE) en haut de la page. Vérifiez d'abord si l'album a déjà été partagé. Une fois le partage effectué, appelez la méthode _showUrlDialog(...).

lib/pages/trip_page.dart

Future<void> _showShareableUrl(BuildContext context) async {
  if (album.shareInfo == null || album.shareInfo.shareableUrl == null) {
    print('Not shared, sharing album first.');
    // Album is not shared yet, share it first, then display dialog
    await _shareAlbum(context);
    _showUrlDialog(context);
  } else {
    // Album is already shared, display dialog with URL
    _showUrlDialog(context);
  }
}

b2f84ff91b0e1396.png Implémentez la méthode _showUrlDialog(...) qui affiche le shareableUrl dans une boîte de dialogue.

lib/pages/trip_page.dart

void _showUrlDialog(BuildContext context) {
  print('This is the shareableUrl:\n${album.shareInfo.shareableUrl}');

  _showShareDialog(
      context,
      'Share this URL with anyone. '
      'Anyone with this URL can access all items.',
      album.shareInfo.shareableUrl);
}

Faites un essai !

L'application répertorie uniquement les voyages qui ne sont pas encore partagés sur l'écran principal. Ne vous inquiétez pas, nous implémenterons cela lors de la prochaine étape. Pour le moment, vous pouvez simplement créer un voyage en quittant l'écran.

b2f84ff91b0e1396.png Ouvrez l'application et sélectionnez un voyage. Sélectionnez SHARE WITH ANYONE (PARTAGER AVEC TOUT LE MONDE) en haut de l'écran, puis ouvrez l'URL renvoyée dans votre navigateur. Remarque : L'URL est également imprimée dans le journal, ce qui vous permet de la copier facilement sur votre ordinateur. Dans Android Studio, le journal s'affiche dans l'onglet Run (Exécuter).

1d1a40c1078e4221.gif

Dans Google Photos, les albums peuvent être partagés via une URL. L'API Library vous permet également de partager des albums par le biais de jetons de partage. Un jeton de partage est une chaîne utilisée dans l'application pour associer des utilisateurs à un album partagé via l'API.

La procédure de partage d'un album via l'API Library se présente comme suit :

  1. L'utilisateur A se connecte à votre application et autorise l'API Library
  2. Création de l'album
  3. Partage de l'album à l'aide de son identifiant
  4. Transfert du jeton de partage à un autre utilisateur

Le processus d'association est similaire :

  1. L'utilisateur B se connecte à votre application et autorise l'API Library
  2. Récupération du jeton de partage de l'album auquel l'utilisateur doit accéder
  3. Accès à l'album à l'aide du jeton de partage

Les albums partagés s'affichent dans l'onglet "Partage" de Google Photos.

Afficher le jeton de partage

À l'étape précédente, vous avez implémenté la méthode _shareAlbum(...) qui permet de partager un album. La propriété shareInfo contient également le "jeton de partage" qui sera affiché à l'écran.

b2f84ff91b0e1396.png Sur la page du voyage, implémentez la méthode _showShareToken(...) qui est appelée lorsque l'utilisateur appuie sur le bouton SHARE WITH FIELD TRIPPA (PARTAGER AVEC FIELD TRIPPA) affiché à l'écran.

lib/pages/trip_page.dart

Future<void> _showShareToken(BuildContext context) async {
  if (album.shareInfo == null) {
    print('Not shared, sharing album first.');
    // Album is not shared yet, share it first, then display dialog
    await _shareAlbum(context);
    _showTokenDialog(context);
  } else {
    // Album is already shared, display dialog with token
    _showTokenDialog(context);
  }
}

Implémentez ensuite l'affichage du "jeton de partage" dans la méthode _showTokenDialog(...). Le jeton fait partie de la propriété shareInfo d'un album.

lib/pages/trip_page.dart

void _showTokenDialog(BuildContext context) {
  print('This is the shareToken:\n${album.shareInfo.shareToken}');
  _showShareDialog(
      context, 'Use this token to share', album.shareInfo.shareToken);
}

Répertorier les albums partagés

Pour le moment, l'application répertorie uniquement les albums appartenant à l'utilisateur, mais pas les albums partagés.

Seuls les albums que l'utilisateur a créés ou explicitement ajoutés à sa photothèque Google Photos apparaissent sur l'écran "Albums" de l'application Google Photos. Seuls ces albums sont renvoyés lorsque vous appelez albums.list dans l'API Library. Toutefois, dans notre application, l'utilisateur peut accéder aux albums partagés d'autres utilisateurs, lesquels sont seulement renvoyés dans l'appel permettant de répertorier les albums partagés. Vous devez modifier la méthode par laquelle la liste de voyages (albums) est extraite de l'API Library afin d'inclure à la fois les albums détenus et les albums partagés.

b2f84ff91b0e1396.png Les albums sont chargés et mis en cache dans le modèle d'API. Modifiez l'implémentation de updateAlbums() dans le modèle pour charger des albums et des albums partagés avant de les stocker sous la forme d'une liste.

Cette configuration utilise plusieurs classes Future pour répertorier les albums de manière asynchrone avant de les combiner au sein de la liste d'albums mis en cache. Supprimez l'ancienne implémentation et mettez en commentaire le nouveau code.

lib/model/photos_library_api_model.dart

void updateAlbums() async {
  // Reset the flag before loading new albums
  hasAlbums = false;
  // Clear all albums
  _albums.clear();
  // Skip if not signed in
  if (!isLoggedIn()) {
    return;
  }
  // Add albums from the user's Google Photos account
  // var ownedAlbums = await _loadAlbums();
  // if (ownedAlbums != null) {
  //   _albums.addAll(ownedAlbums);
  // }

  // Load albums from owned and shared albums
  final list = await Future.wait([_loadSharedAlbums(), _loadAlbums()]);

  _albums.addAll(list.expand((a) => a ?? []));

  notifyListeners();
  hasAlbums = true;
}

Associer un album partagé

Vous pouvez associer les utilisateurs de votre application à un album en utilisant le jeton de partage. Pour ce faire, il vous suffit d'utiliser une boîte de dialogue de texte dans cet atelier de programmation.

b2f84ff91b0e1396.png Implémentez la méthode _joinTrip sur la page "Join trip" qui appelle le modèle d'API avec le jeton de partage saisi par l'utilisateur. Affichez l'indicateur de chargement, effectuez l'appel pour associer l'album partagé à l'entrée du formulaire de texte, puis masquez l'indicateur de chargement et revenez à l'écran précédent.

lib/pages/join_trip_page.dart

Future<void> _joinTrip(BuildContext context) async {
  // Show loading indicator
  setState(() => _isLoading = true);

  // Call the API to join an album with the entered share token
  await ScopedModel.of<PhotosLibraryApiModel>(context)
      .joinSharedAlbum(shareTokenFormController.text);

  // Hide loading indicator
  setState(() => _isLoading = false);

  // Return to the previous screen
  Navigator.pop(context);
}

Faites un essai !

Pour tester cette partie de l'atelier de programmation, vous aurez besoin d'un deuxième appareil ou émulateur avec un autre compte utilisateur.

b2f84ff91b0e1396.png Créez et partagez un voyage sous un seul utilisateur, puis sélectionnez l'option SHARE IN FIELD TRIPPA (PARTAGER DANS FIELD TRIPPA) pour récupérer le jeton de partage. Copiez ce jeton de partage sur l'autre appareil ou émulateur, puis saisissez-le via l'option JOIN A TRIP ALBUM (ASSOCIER UN ALBUM DE VOYAGES) sur la page d'accueil. (Conseil : Le presse-papiers est partagé entre les émulateurs et votre ordinateur hôte.)

8043086cc00eaa16.gif 55c1e75014d4d2a4.gif

Conseils pour une implémentation réelle

Lorsque vous implémentez le partage dans une application réelle (et non dans un atelier de programmation), vous devez bien réfléchir à la façon dont vous pouvez utiliser les jetons de partage pour associer des utilisateurs à des albums. Pensez à les stocker dans votre backend sécurisé, et à utiliser les relations entre les utilisateurs pour créer et associer des albums.

Par exemple, une application de rencontre d'un club de football peut effectuer le suivi des participants à des événements planifiés et ne les associer à l'album qu'après les avoir invités.

Avant d'apporter des modifications au compte Google Photos de vos utilisateurs, il est important de les prévenir et de leur demander leur autorisation. Pour en savoir plus, consultez les consignes relatives à l'expérience utilisateur de l'API Library de Google Photos.

Opérations effectuées

  • Implémentation d'une fonctionnalité de partage dans votre application, avec Google Photos
  • Création de vos propres fonctionnalités de partage de photos et de vidéos par-dessus l'API Library de Google Photos, sans avoir à vous soucier de l'infrastructure ni de l'espace de stockage
  • Utilisation de la fonctionnalité de partage intégrée à l'API de façon innovante pour partager du contenu directement avec les utilisateurs
  • Utilisation de certains éléments clés de l'API Library
  • Création d'albums et importation de nouvelles photos
  • Limitation des albums partagés affichés aux seuls albums créés par votre application

Étapes suivantes

Pour en savoir plus sur le partage de contenus multimédias et d'autres éléments de l'API Library, consultez la documentation pour les développeurs des API Google Photos à l'adresse https://developers.google.com/photos. Il peut s'agir, par exemple, de filtres de contenu intelligent, basés sur le machine learning, qui vous aident à trouver les photos et les vidéos qui vous intéressent.

Lorsque vous êtes prêt à lancer votre intégration, rejoignez le Programme Partenaire Google Photos.

N'oubliez pas de consulter les Consignes relatives à l'expérience utilisateur et les Bonnes pratiques techniques. Pour vous aider à démarrer, des bibliothèques clientes sont également disponibles dans certains langages.