Flutter Plugin For Importing Stickers Into Telegram

Telegram recently has announced a new contest.

Message from https://t.me/ContestBot

Given: a sticker import mechanism for Android and iOS apps.

Task: write an Android or iOS app that uses this mechanism.

The timing is very limited, the deadline is the 4th of July. Objectively, I don’t have time to write an app in such a short time. I decided to help the Flutter developers in this contest and write a plugin to work with the native SDK. The article will dwell on that.

Let’s see what kind of import mechanism Telegram offers us.

Android

The official repository is here. There is no SDK. To import stickers, you just need to send Intent with a set of parameters. What could be easier?

Intent intent = new Intent(CREATE_STICKER_PACK_ACTION);
intent.putExtra(Intent.EXTRA_STREAM, stickers);
intent.putExtra(CREATE_STICKER_PACK_IMPORTER_EXTRA, getPackageName());
intent.putExtra(CREATE_STICKER_PACK_EMOJIS_EXTRA, emojis);
intent.setType("image/*");

The difficulty is that you need to give permission to a third-party application so it can get access to any of your files (we are not considering the raw directory case). You can read more about file sharing between applications in official documentation.

Use FileProvider to allow access to your files. Basically, we describe which directories we want to give access to, and also describe the name that will hide the real path to the files.

For simplicity, I’ve prepared one folder in the directory with the cache. In case if you want to use some other folder, you will need to configure the manifest:

...
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
...

and add an xml file describing the available paths:

<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path path="telegram_stickers_import/" name="telegram_stickers_import" />
</paths>

When used in this way, the path:

/data/user/0/com.otopba.telegram_stickers_import_example/cache/telegram_stickers_import/sticker1.webp

Turns into:

content://com.otopba.telegram_stickers_import_example.provider/telegram_stickers_import/sticker1.webp

iOS

The official repository is here. Telegram provides SDK for iOS and has even made data validation with human-readable errors.

You need to add a few lines to Info.plist to make it work:

<key>LSApplicationQueriesSchemes</key>
<array>
<string>tg</string>
</array>

How to use the plugin

As expected, the plugin is as simple as possible: one method where you need to pass your stickerset for import:

class TelegramStickersImport {
/// Folder inside cache directory for store your stickers
static const androidImportFolderName = "telegram_stickers_import";
static const MethodChannel _channel = MethodChannel(
'telegram_stickers_import',
);
/// Method for import sticker set
static Future<String?> import(StickerSet stickerSet) async {
return _channel.invokeMethod('import', stickerSet.toMap());
}
}

The nuance is in reading the sticker files:

  • to run the Android app, you will need to copy your stickers files to the cache/telegram_stickers_import folder (or one that you set up by yourself);
  • for the iOS application you will need to read the contents of the stickers into the Uint8List.
StickerData({this.path, this.bytes});/// Android factory
factory StickerData.android(String path) {
return StickerData(path: path);
}
/// iOS factory
factory StickerData.iOS(Uint8List bytes) {
return StickerData(bytes: bytes);
}

Conclusion

It’s strange that Telegram made an SDK only for iOS, and Android developers, as always, should do their rain dance.

I will be glad if you use my plugin.

I’m looking forward to the Pull Requests.

Ciao!

Android developer / Flutter enthusiast