Функции устройства
Мост веб-API
Нативные полифилы для уведомлений, «Поделиться», буфера обмена и не только
1Что такое мосты Web API?#
Android WebView не поддерживает несколько современных Web API, которые есть в Chrome. Созданное вами приложение автоматически добавляет полифилы для этих API, поэтому сайты работают так же, как в Chrome:
✅ Веб-уведомления (Notification API)
✅ Web Share (navigator.share)
✅ Буфер обмена (navigator.clipboard)
✅ window.close()
✅ ссылки target="_blank" и window.open()
Настройка не нужна — это автоматически работает в каждом созданном приложении.
2Веб-уведомления#
Сайты, использующие Notification.requestPermission() и new Notification(), будут показывать настоящие уведомления Android.
- На Android 13+ пользователь видит системное окно запроса разрешения
- На Android 12 и ниже уведомления разрешены по умолчанию
- Нажатие на уведомление открывает приложение
- Параметр «tag» заменяет предыдущие уведомления (как в веб-спецификации)
// Your website JS — works the same as in Chrome:
Notification.requestPermission().then(function(result) {
if (result === 'granted') {
new Notification('Hello!', {
body: 'This is a native Android notification',
tag: 'my-notif'
});
}
});3Web Share API#
navigator.share() открывает нативное окно «Поделиться» Android, позволяя отправлять контент в WhatsApp, Telegram, почту и другие приложения.
- Поддерживает title, text и url
- navigator.canShare() возвращает true
- Работает точно так же, как окно «Поделиться» в Chrome
// Share content from your website:
navigator.share({
title: 'Check this out',
text: 'Amazing content!',
url: 'https://example.com/page'
});4API буфера обмена#
navigator.clipboard.writeText() и readText() связаны с нативным буфером обмена Android.
- writeText() копирует текст в системный буфер обмена
- readText() читает из системного буфера обмена
- Оба возвращают Promise (как в веб-спецификации)
// Copy to clipboard:
await navigator.clipboard.writeText('Hello World');
// Read from clipboard:
const text = await navigator.clipboard.readText();5window.close() и target="_blank"#
Также исправлены две распространённые проблемы WebView:
- window.close() — закрывает/завершает активность приложения (полезно для страниц обратного вызова оплаты/авторизации)
- ссылки target="_blank" — открываются внутри WebView, а не молча отбрасываются
- вызовы window.open() — обрабатываются так же
Менять сайт не нужно — это просто работает.
6Сопоставление доменов для внешних ссылок#
Когда установлено «Внешние ссылки → Открывать в браузере», приложение умно сопоставляет домены:
- google.com и www.google.com считаются одним и тем же доменом
- В Chrome открываются только действительно другие домены
- Перенаправления в пределах одного сайта остаются в WebView
Это устраняет проблему, когда сайт вроде google.com перенаправляет на www.google.com и случайно открывается в Chrome.
7Ссылки UPI и платёжных приложений (Razorpay, GPay, PhonePe, Paytm)#
Любая ссылка, схема которой не является веб-страницей, автоматически открывает приложение Android, которому она принадлежит, — без настройки и без списка схем:
- upi://pay — общий UPI-интент (пользователь выбирает своё приложение UPI)
- paytmmp:// (Paytm), phonepe://, tez:// (Google Pay), gpay://
- tel:, mailto:, sms:, whatsapp://, tg://, intent://
Это работает везде, куда может перейти страница:
✅ нажатая ссылка <a href="upi://pay?...">
✅ JS-перенаправление (window.location.href = 'upi://...')
✅ всплывающее окно — window.open('paytmmp://...') — именно так Razorpay Checkout передаёт управление приложениям UPI
Поэтому страницы оплаты Razorpay / Cashfree / PhonePe работают как есть: покупатель выбирает вариант UPI, открывается платёжное приложение, он подтверждает платёж, а обработчик успеха на вашей странице срабатывает, когда он возвращается. Если ни одно приложение на телефоне не может обработать схему, пользователь увидит понятное сообщение вместо пустой страницы ошибки.
⚠️ Продаёте ЦИФРОВЫЕ товары в приложении для Play Store? Google требует для них Play Billing — используйте руководство по покупкам в приложении. Оплата через UPI/карту подходит для физических товаров, услуг и приложений, распространяемых вне Play.
<!-- Simplest form — a plain UPI intent link. The user's phone
shows every installed UPI app (GPay/PhonePe/Paytm/BHIM): -->
<a href="upi://pay?pa=merchant@bank&pn=MyStore&am=99.00&cu=INR&tn=Order%20123">
Pay ₹99 via UPI
</a>8Полный пример — Razorpay Checkout с UPI от начала до конца#
Полный пример, который можно скопировать, с использованием Razorpay Checkout. Что происходит на телефоне:
- Покупатель нажимает «Оплатить ₹499» → на странице открывается Razorpay Checkout
- Покупатель выбирает UPI → автоматически открывается его приложение UPI (это передача управления через paytmmp:// / phonepe://, которую приложение выполняет за вас)
- Покупатель подтверждает платёж в приложении UPI и возвращается — Android сам возвращает ваше приложение
- Функция-обработчик вызывается с ID платежа → покажите свой экран успеха
- dismiss срабатывает при отмене → дайте возможность повторить
Замените rzp_test_XXXXXXXX своим ключом из dashboard.razorpay.com. Сначала тестируйте с ключом key_test — в тестовом режиме Razorpay имитируется подтверждение UPI.
⚠️ В реальном магазине подтверждайте платёж на сервере (вебхук Razorpay или Orders API + проверка подписи) перед отправкой товара — обработчик в браузере можно подделать.
<!doctype html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<h2>Premium Plan — ₹499</h2>
<button id="payBtn">Pay ₹499</button>
<p id="result"></p>
<script>
document.getElementById('payBtn').onclick = function () {
var rzp = new Razorpay({
key: 'rzp_test_XXXXXXXX', // your Razorpay Key ID
amount: 49900, // paise — ₹499.00
currency: 'INR',
name: 'My Store',
description: 'Premium Plan',
prefill: { contact: '', email: '' },
theme: { color: '#2563eb' },
// Fires after the customer returns from their UPI app
handler: function (response) {
document.getElementById('result').textContent =
'✅ Paid! Payment ID: ' + response.razorpay_payment_id;
// Real store: send response.razorpay_payment_id to your
// server / webhook flow and verify before unlocking anything.
},
modal: {
ondismiss: function () {
document.getElementById('result').textContent =
'Payment cancelled — tap Pay to try again.';
}
}
});
rzp.open();
};
</script>