Розробка розширення для Share Sheet (Android)
Користувач натиснув Share, але ваш додаток не з'явився у списку. Або з'явився, але впав з SecurityException. Знайома ситуація? Типові причини — неправильний intent-filter або відсутність обробки ContentResolver. Розберемо, як побудувати надійний Share Extension, який коректно приймає будь-які типи контенту — від тексту до відео — та персоналізує шеринг через Direct Share.
В Android 10+ модель доступу до файлів змінилася: прямий шлях до файлу не отримати. Кожен content:// URI потребує тимчасового дозволу, який діє тільки під час активності Activity. Ігнорування цього правила веде до падінь на Android 11 та вище. Ми розповімо, як уникнути цих помилок та забезпечити стабільну обробку контенту на всіх актуальних версіях.
Наше рішення включає перевірені патерни: роздільні intent-filter для кожного MIME-типу, безпечне копіювання файлів через ContentResolver та персоналізований Direct Share для підвищення конверсії. Ви отримаєте готовий код, який вже протестовано на Android 10–14. Це економить час на налагодження та гарантує сумісність.
Як налаштувати intent-filter для декількох MIME-типів?
Головна помилка — один фільтр на все. Система Android погано обробляє декілька <data> всередині одного <intent-filter>. Правильний підхід: створюємо окремі фільтри для text/plain, image/*, video/*, application/octet-stream. Приклад:
<intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="image/*" /> </intent-filter> Для SEND_MULTIPLE додаємо аналогічні фільтри. Це гарантує появу додатку в Chooser для кожного типу.
Як обробляти URI без втрати даних?
Uri з Intent.EXTRA_STREAM живе тільки під час активності (якщо не взято persistedUriPermission). Читати його потрібно через ContentResolver.openInputStream(), а не File(). Ми копіюємо файл в cacheDir одразу:
val inputStream = contentResolver.openInputStream(sourceUri) val destFile = File(cacheDir, "shared_${System.currentTimeMillis()}.jpg") inputStream?.use { it.copyTo(destFile.outputStream()) } Так файл доступний навіть після завершення Activity. На Android 10+ прямий доступ до /data/ заблоковано, тому цей pattern обов'язковий.
Чому Direct Share збільшує конверсію?
Direct Share показує персоналізованих отримувачів прямо в системному шерингу. За даними A/B-тестів, конверсія таких шерингів вища в 2–3 рази порівняно з базовим Chooser. Реалізується через ShortcutManagerCompat.pushDynamicShortcut() з категорією SHORTCUT_CATEGORY_CONVERSATION:
val shortcut = ShortcutInfoCompat.Builder(context, "chat_anna") .setShortLabel("Анна") .setLongLived(true) .setCategories(setOf(ShortcutInfoCompat.SHORTCUT_CATEGORY_CONVERSATION)) .setIntent(Intent(context, ChatActivity::class.java).apply { putExtra("user_id", 42) }) .build() ShortcutManagerCompat.pushDynamicShortcut(context, shortcut) Це окрема робота: потрібно підтримувати актуальність shortcuts, оновлювати аватарки, реагувати на зміни контактів. Але результат того вартий.
Порівняння підходів
| Характеристика | Базовий Share | З Direct Share |
|---|---|---|
| Час розробки | 2–3 тижні | 4–6 тижнів |
| Конверсія шерингу | стандартна | +150% |
| Обробка файлів | тільки online | фонова синхронізація |
| Персоналізація | ні | так, з аватарками |
| Складність інтеграції | низька | середня |
Типові проблеми та їх рішення
| Проблема | Рішення |
|---|---|
| Додаток не з'являється в Chooser | Перевірити intent-filter: розділити по MIME-типах, додати SEND_MULTIPLE |
| SecurityException при відкритті URI | Використовувати ContentResolver.openInputStream() замість File() |
| Втрата даних при повороті екрану | Зберігати скопійований шлях в onSaveInstanceState |
| Неправильний back-стек | Налаштувати launchMode="singleTask" та taskAffinity |
Чек-лист тестування Share Extension
- Перевірити одиночний та множинний шеринг тексту, зображень, відео. - Перевірити на Android 10, 12, 14 (на емуляторі та реальних пристроях). - Переконатися, що додаток з'являється в Chooser для всіх цільових типів. - Перевірити Direct Share: чи відображаються персоналізовані контакти. - Симулювати переривання (дзвінок, поворот) до завершення обробки.Що входить в роботу
- Аналіз типів контенту, які повинен приймати додаток.
- Проектування intent-filter та UI вибору (при необхідності).
- Реалізація Activity-приймача з обробкою URI та копіюванням.
- Налаштування Direct Share з підтримкою актуальних shortcuts.
- Тестування на Android 10–14 з реальними файлами та текстом.
- Документація з інтеграції та підтримка при деплої.
- Економія часу на налагодження за рахунок готових рішень.
Процес роботи
- Аналіз — вивчаємо типи контенту, які ваш додаток повинен приймати.
- Проектування — вибираємо схему intent-filter, проектуємо UI вибору (якщо потрібно).
- Розробка — пишемо Activity-приймач, обробляємо URI, реалізуємо копіювання.
- Тестування — перевіряємо на Android 10, 12, 14 з різними файлами та текстом.
- Деплой — публікуємо в Google Play, налаштовуємо Google Play Console для прийому посилань.
Строки та вартість
Оцінимо ваш проект за 1–2 дні. Базове розширення — від 2 тижнів. Складні інтеграції — до 6 тижнів. Вартість фіксується після узгодження ТЗ. У нас 5+ років досвіду в Android-розробці, понад 20 успішних Share Extension. Отримайте готове рішення з гарантією сумісності на Android 10–14. Замовте розробку Share Extension прямо зараз — почнемо з консультації.
Згідно з Android Developer Guide, для надійного прийому контенту використовуйте окремі intent-filter на кожен MIME-тип.
Зв'яжіться з нами, щоб обговорити ваш проект та отримати індивідуальну пропозицію.







