Utiliser les fonctionnalités de partage social des smartphones et tablettes

(màj du 28/07/2021)

Cette page a été écrite à l'origine en novembre 2018. Depuis quelques modifications sont nécessaires pour fonctionner correctement sur les versions récentes d'Android.

En effet, l'action de partage de textes et images nécessite qu'on ait au préalable activé le droit "secure file sharing" dans Projet / Options / Application / Liste des droits de la plateforme Android. Ceci n'est pas nécessaire pour les autres plateformes.


Lorsqu'on édite des applications mobiles se pose toujours la question de les faire connaître parmi des millions d'autres sans se ruiner en achats publicitaires incertains. La méthode la plus simple est l'utilisation du bouche à oreilles et donc des partages sur les réseaux sociaux.

Pour cela les systèmes d'exploitation mobiles fournissent une API simple :

  • On choisit ce qu'on veut partager : texte et/ou image.
  • On le transmet au système de partage.
  • L'appareil affiche une fenêtre proposant la liste des applications ou services compatibles avec notre contenu.
  • L'utilisateur partage, transmets, imprime ou annule.
  • Notre application reprend la main.

Le sujet s'est posé pour moi lorsque j'ai développé Pumpkin Killer: un petit jeu gratuit ne peut pas se propager sans un coup de pouce ou deux. La visibilité par les utilisateurs est primordiale. Le plus simple étant de proposer aux utilisateurs de partager leur score sur les réseaux sociaux dont ils ont l'habitude. Plutôt que gérer moi-même les API de chaque réseau social il était plus simple d'utiliser le système de partage intégré. Voici donc comment faire de même depuis un programme développé en Delphi.

La capture d'image

Partager du texte, c'est simple. Il suffit de savoir quoi dire, concaténer les contenus dans une chaine et c'est plié. En revanche je voulais aussi partager une image annonçant le score. Pour ça il y avait plusieurs solutions :

  1. capturer l'image affichée à l'écran où se trouvent déjà toutes les informations
  2. dessiner une image spécialement pour l'occasion
  3. passer par un système en ligne qui aurait généré une image "sociale" à la demande.

La solution 3 est faisable car les sites chargent quasiment tous un visuel lié au site lorsqu'ils croisent une URL. Il était donc techniquement possible de générer une image en PHP, en Delphi ou autre langage à exécuter côté serveur pour ça. Le hic c'est que si le jeu est un succès, son hébergement peut rapidement exploser alors que le jeu est totalement indépendant d'Internet. Une grosse erreur de conception !
Si j'avais opté pour cette solution, cette page ne serait pas ici mais sur ce blog, donc ce n'est pas la solution choisie. wink

La solution 2 était une option. Reste que je n'étais pas inspiré pour un visuel aléatoire assez attractif pour qu'il soit partagé et qui ne constituerait pas une surprise pour le joueur qui fait la demande de partage.

Restait donc la solution 1.

Les composants visuels sous Firemonkey ont tous une méthode MakeScreenShot() qui permet d'en capturer le canvas. Ce n'est étrangement pas le cas des TForm. On a cependant une autre méthode qui peut servir à ça.

La classe TForm publie la méthode PaintTo(). Elle redessine la fiche dans le canvas passé en paramètre.

J'ai donc commencé par créer un TBitmap de la bonne taille, le vider puis y dessiner l'écran après avoir désactivé les boutons que je ne voulais pas y voir.

Pas la peine de traiter la file de messages par un Application.ProcessMessages() à ce moment là, je n'ai pas besoin que ces modifications se voient à l'écran.
Pas besoin non plus de verrouiller le canvas avec BeginScene() et EndScene() puisque PaintTo() s'en charge.

// désactivation des éléments d'interface que je ne veux pas dans la capture d'écran
btnPartage.Visible := false;
btnRetourGameOver.Visible := false;
// Création du TBitmap
img := tbitmap.Create;
try
  // Mise à la taille de l'écran
  img.SetSize(width, height);
  PaintTo(img.Canvas);
  // utilisation du TBitmap généré
  // ...
finally
  // réactivation des éléments d'interface masqués
  btnPartage.Visible := true;
  btnRetourGameOver.Visible := true;
  // libération du TBitmap créé pour l'occasion
  freeandnil(img);
end;

Avec la VCL j'aurais pu utiliser la méthode GetFormImage() qui retourne un TBitmap de la fiche... en revanche je n'aurais pas eu accès à l'API de partage qui n'est pas disponible sous Windows.

Les listes d'actions

Plutôt que nous compliquer les choses avec des classes à chercher dans la documentation ou des API à appeler en direct, Embarcadero propose des actions standards pour les principales opérations liées aux systèmes d'exploitation mobiles. C'est le cas des prises de photos ou des accès à la bibliothèque de photos comme pour l'appel du système de partage de l'OS.

J'ai donc ajouté une TActionList à ma fiche puis suis entré dans son éditeur de listes d'actions afin de créer une action standard de sa rubrique "Bibliothèque multimédia".

J'aurais aussi pu créer à la main une instance de TShowShareSheetAction et l'exécuter, mais tant qu'à avoir une fiche, autant passer par le concepteur de fiches.

Ceci fait, j'avais donc mon composant d'affichage des fenêtres de partage de l'OS.

Le composant TShowShareSheetAction demande qu'on renseigne un texte dans sa propriété TextMessage et/ou une image dans sa propriété Bitmap. Il suffit ensuite d'appeler sa méthode Execute(). Simple, non ?

L'API de partage

Pour le partage lui-même, ça se recomplique un tantinet. J'avais deux cibles principales : Twitter et Facebook.

Au départ je voulais diffuser un texte contenant l'URL de téléchargement du jeu et l'accompagner d'une photo du score.

En pratique il semble que l'application Twitter sur Android n'accepte pas le partage des deux à la fois alors qu'elle les prend sur iOS. Bizarre mais c'est le problème classique des logiciels développés en parallèle par deux équipes différentes dans deux langages différents... Heureusement Delphi nous épargne assez bien ces écarts de plateformes.

Donc pour Android je me suis résigné à ne partager que du texte. Et faire les deux pour iOS.

Le partage se faisant depuis un bouton d'interface j'ai tout mis dans son événement onClick et n'ai rien modifié du côté du composant actPartage (mon TShowShareSheetAction). Voici donc le code final pour partager le score et/ou l'image depuis le jeu.

procedure TfrmMain.btnPartageClick(Sender: TObject);
{$IFDEF IOS}
var
  img: tbitmap;
{$ENDIF}
begin
  actPartage.TextMessage := 'J''ai atteint le niveau ' + score.niveau.ToString +
    ' avec le score de ' + score.score.ToString +
    ' points sur Pumpkin Killer. Feras-tu mieux que moi ? #pumpkinkiller #gamolf https://pumpkinkiller.gamolf.fr';
{$IFDEF IOS}
  btnPartage.Visible := false;
  btnRetourGameOver.Visible := false;
  img := tbitmap.Create;
  try
    img.SetSize(width, height);
    PaintTo(img.Canvas);
    actPartage.Bitmap.Assign(img);
  finally
    btnPartage.Visible := true;
    btnRetourGameOver.Visible := true;
    freeandnil(img);
  end;
{$ENDIF}
  actPartage.Execute;
end;

Avec ça je compte sur la famille et les amis pour télécharger le jeu, y jouer, partager... et sur vous si vous avez un peu de temps à passer dessus dans un train, un métro ou un bus.

Et voici ce que donne un tweet partagé depuis mon iPad:

J'ai atteint le niveau 6 avec le score de 3096 points sur Pumpkin Killer. Feras-tu mieux que moi ? #pumpkinkiller #gamolf #halloween #gamedev #indiegame https://t.co/PgfcZmgu6o pic.twitter.com/yzExdMO4NX

— Patrick Prémartin (@PremartinPatric) 30 octobre 2018

Blague à part vous l'avez vu, c'est facile de faire du partage en tant qu'application utilisatrice. Ca l'est moins en tant qu'appication consommatrice, j'y reviendrai un jour.

Si vous avez des applications mobiles, pensez à intégrer cette fonctionnalité, c'est pas grand chose mais ça fait toujours un peu de visibilité gratuite.


(màj du 23/07/2022)

Mieux que de conditionner des blocs de code en fonction de la plateforme vous pouvez aussi utiliser les services de plateforme afin de savoir si le partage est pris en charge par Delphi sur ce système d'exploitation (ce qui permet aussi de savoir si l'API existe). Pour cela il vous faudra les unités FMX.Platform et FMX.MediaLibrary où est déclarée l'interface IFMXShareSheetActionsService.


Mug Toucan DX dans la baie de RioMug Chinese New Year 2023 : year of the rabbit