Jednym z najskuteczniejszych sposobów na zachęcenie nowych użytkowników do zainstalowania Twojej aplikacji jest umożliwienie użytkownikom udostępniania treści z Twojej aplikacji znajomym. Dzięki łączom dynamicznym możesz stworzyć doskonałe środowisko udostępniania między użytkownikami: użytkownicy, którzy otrzymują rekomendacje treści od swoich znajomych, mogą kliknąć łącze i zostać przeniesieni bezpośrednio do udostępnionej treści w Twojej aplikacji, nawet jeśli muszą przejść do aplikacji Sklep lub Sklep Google Play, aby najpierw zainstalować aplikację.
Łącząc lepkość skierowań użytkowników i trwałość linków dynamicznych, możesz tworzyć funkcje udostępniania i polecania między użytkownikami, które przyciągają nowych użytkowników, przyciągając ich bezpośrednio do treści Twojej aplikacji lub udostępniając promocje przynoszące obopólne korzyści stronie odsyłającej i polecanej .
Kluczowe korzyści
- Nowi użytkownicy, którzy otwierają Twoją aplikację po raz pierwszy, otrzymują spersonalizowane środowisko pierwszego uruchomienia, które jest dostosowane do kontekstu na podstawie tego, co ich znajomy chciał im udostępnić. Możesz na przykład wyświetlić zawartość, która została im udostępniona, lub automatycznie połączyć ich ze znajomym, który ich zaprosił.
- Ułatwia użytkownikom udostępnianie treści znajomym na różnych platformach, niezależnie od tego, czy ich znajomi mają zainstalowaną Twoją aplikację.
Oto jak zacząć!
Skonfiguruj Firebase i pakiet Dynamic Links SDK
Skonfiguruj nowy projekt Firebase i zainstaluj pakiet SDK Dynamic Links w swojej aplikacji.
Zainstalowanie pakietu Dynamic Links SDK umożliwia Firebase przekazywanie danych o łączu dynamicznym do aplikacji, także po zainstalowaniu aplikacji przez użytkownika.
Twórz łącza dynamiczne
Teraz nadszedł czas, aby skonfigurować linki, które użytkownicy mogą wysyłać do swoich znajomych. Nie martw się, jeśli znajomi Twoich użytkowników nie mają jeszcze zainstalowanej aplikacji; Linki dynamiczne mogą zająć się tym za Ciebie.
Dla każdego elementu treści, który chcesz udostępnić, utwórz link dynamiczny .
Podczas tworzenia łącza dynamicznego musisz podać adres URL HTTP lub HTTPS jako parametr link
, który będzie używany do identyfikowania udostępnianych treści. Jeśli masz witrynę z podobną treścią, użyj adresów URL swojej witryny. Zapewni to prawidłowe renderowanie tych linków na platformie, która nie obsługuje linków dynamicznych, takiej jak przeglądarka na komputerze. Na przykład:
https://example.page.link/?link=https://www.example.com/content?item%3D1234&apn=com.example.android&ibi=com.example.ios&isi=12345
Możesz także dodać dodatkowe informacje do ładunku danych, dodając parametry zakodowane w adresie URL — na przykład, aby wskazać, że łącze jest przeznaczone dla określonego użytkownika, na przykład w zaproszeniu do gry.
https://example.page.link/?link=https://www.example.com/invitation?gameid%3D1234%26referrer%3D555&apn=com.example.android&ibi=com.example.ios&isi=12345
Zanim udostępnisz te linki, możesz użyć interfejsu API skracania adresów URL Firebase Dynamic Links, aby wygenerować bardziej przyjazne adresy URL. Krótki link dynamiczny wygląda jak w poniższym przykładzie:
https://example.page.link/WXYZ
Niezależnie od tego, którego łącza użyjesz, gdy użytkownicy otworzą łącze dynamiczne na swoim urządzeniu, aplikacja określona przez parametr apn
(w systemie Android) lub parametry ibi
i isi
(w systemie iOS) przekieruje użytkowników do Sklepu Play lub App Store w celu zainstalowania aplikacji jeśli nie jest jeszcze zainstalowany. Następnie, gdy aplikacja jest instalowana i otwierana, adres URL określony w parametrze „link” jest przekazywany do aplikacji.
Dodaj przyciski „Udostępnij”, które wysyłają linki dynamiczne
Najpierw spójrz na ten prosty przykład aplikacji czatu obsługującej pokoje, takiej jak Hangouts, która generuje linki umożliwiające zapraszanie osób do pokojów rozmów.
iOS


Android


Szybki
func generateContentLink() -> URL { let baseURL = URL(string: "https://your-custom-name.page.link")! let domain = "https://your-app.page.link" let linkBuilder = DynamicLinkComponents(link: baseURL, domainURIPrefix: domain) linkBuilder?.iOSParameters = DynamicLinkIOSParameters(bundleID: "com.your.bundleID") linkBuilder?.androidParameters = DynamicLinkAndroidParameters(packageName: "com.your.packageName") // Fall back to the base url if we can't generate a dynamic link. return linkBuilder?.link ?? baseURL }
Cel C
- (NSURL *)generateContentLink { NSURL *baseURL = [NSURL URLWithString:@"https://your-custom-name.page.link"]; NSString *domain = @"https://your-app.page.link"; FIRDynamicLinkComponents *builder = [[FIRDynamicLinkComponents alloc] initWithLink:baseURL domainURIPrefix:domain]; builder.iOSParameters = [FIRDynamicLinkIOSParameters parametersWithBundleID:@"com.your.bundleID"]; builder.androidParameters = [FIRDynamicLinkAndroidParameters parametersWithPackageName:@"com.your.packageName"]; // Fall back to the base url if we can't generate a dynamic link. return builder.link ?: baseURL; }
Kotlin+KTX
fun generateContentLink(): Uri { val baseUrl = Uri.parse("https://your-custom-name.page.link") val domain = "https://your-app.page.link" val link = FirebaseDynamicLinks.getInstance() .createDynamicLink() .setLink(baseUrl) .setDomainUriPrefix(domain) .setIosParameters(DynamicLink.IosParameters.Builder("com.your.bundleid").build()) .setAndroidParameters(DynamicLink.AndroidParameters.Builder("com.your.packageName").build()) .buildDynamicLink() return link.uri }
Java
public static Uri generateContentLink() { Uri baseUrl = Uri.parse("https://your-custom-name.page.link"); String domain = "https://your-app.page.link"; DynamicLink link = FirebaseDynamicLinks.getInstance() .createDynamicLink() .setLink(baseUrl) .setDomainUriPrefix(domain) .setIosParameters(new DynamicLink.IosParameters.Builder("com.your.bundleid").build()) .setAndroidParameters(new DynamicLink.AndroidParameters.Builder("com.your.packageName").build()) .buildDynamicLink(); return link.getUri(); }
Po utworzeniu łącza dynamicznego możesz dodać przycisk udostępniania do interfejsu użytkownika, który uruchomi standardowy przepływ udostępniania platformy:
Szybki
lazy private var shareController: UIActivityViewController = { let activities: [Any] = [ "Learn how to share content via Firebase", URL(string: "https://firebase.google.com")! ] let controller = UIActivityViewController(activityItems: activities, applicationActivities: nil) return controller }() @IBAction func shareButtonPressed(_ sender: Any) { let inviteController = UIStoryboard(name: "Main", bundle: nil) .instantiateViewController(withIdentifier: "InviteViewController") self.navigationController?.pushViewController(inviteController, animated: true) }
Cel C
- (UIActivityViewController *)shareController { if (_shareController == nil) { NSArray *activities = @[ @"Learn how to share content via Firebase", [NSURL URLWithString:@"https://firebase.google.com"] ]; UIActivityViewController *controller = [[UIActivityViewController alloc] initWithActivityItems:activities applicationActivities:nil]; _shareController = controller; } return _shareController; } - (IBAction)shareLinkButtonPressed:(UIView *)sender { if (![sender isKindOfClass:[UIView class]]) { return; } self.shareController.popoverPresentationController.sourceView = sender; [self presentViewController:self.shareController animated:YES completion:nil]; }
Kotlin+KTX
private fun onShareClicked() { val link = DynamicLinksUtil.generateContentLink() val intent = Intent(Intent.ACTION_SEND) intent.type = "text/plain" intent.putExtra(Intent.EXTRA_TEXT, link.toString()) startActivity(Intent.createChooser(intent, "Share Link")) }
Java
private void onShareClicked() { Uri link = DynamicLinksUtil.generateContentLink(); Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(Intent.EXTRA_TEXT, link.toString()); startActivity(Intent.createChooser(intent, "Share Link")); }
W tym przykładzie domyślny interfejs udostępniania automatycznie wyświetla listę aplikacji do udostępniania łącza, więc jest to coś, co możesz skonfigurować we własnej aplikacji za pomocą zaledwie kilku wierszy kodu.
Zamiast wybierać kontakty i redagować wiadomość w Twojej aplikacji, te działania są delegowane do aplikacji wybranej w oknie dialogowym udostępniania. Ponadto delegowanie udostępniania innym aplikacjom oznacza, że nie musisz pytać użytkownika o uprawnienia do kontaktów i umożliwia użytkownikom wybieranie z rozszerzonej listy kontaktów w wybranej przez nich aplikacji. Aby lepiej ułatwić udostępnianie w mediach społecznościowych, możesz dodać metadane podglądu mediów społecznościowych do łącza dynamicznego, które będzie wyświetlane wraz z łączem w głównych kanałach społecznościowych.
Czasami jednak wysłanie samego linku bez tekstu nie wystarczy, aby uzyskać przekonujące polecenie. Dołączając do linku krótką wiadomość i, jeśli to możliwe, bogatszą prezentację, użytkownicy mogą zrozumieć propozycję wartości skierowania, gdy go otrzymają:
iOS


Android


Chociaż jest to bardziej złożone niż w ostatnim przykładzie, podejście będzie mniej więcej takie samo. Na tym ekranie znajduje się duża grafika z propozycją wartości zaproszenia i przyciskami udostępniania w głównych kanałach społecznościowych. W tym przepływie interfejsu użytkownika występuje pewna nadmiarowość — niektóre kanały udostępniania są prezentowane indywidualnie, aby umożliwić bardziej spersonalizowane wiadomości dla poszczególnych kanałów, takie jak dodanie wiersza tematu do zaproszeń e-mail. W tym menu zaproszeń:
- Prezentuj przyciski udostępniania wiadomości e-mail, wiadomości tekstowych i kopiowania linków oraz odpowiednio dostosuj ich komunikaty. E-mail będzie zawierał temat i może zawierać dłuższą treść z podziałem linii, obrazami i spacjami; tekst powinien zawierać krótszą treść z podziałami wierszy, ale z niewielką ilością białych znaków i bez obrazów; a kopiowanie linków powinno po prostu kopiować link i nic więcej.
- Używaj systemowego interfejsu użytkownika do wszystkich innych czynności, w tym krótkiej wiadomości z zaproszeniem dołączonej do łącza.
- Precyzyjny link poprzez schemat adresu URL lub uniwersalny link do innej aplikacji, która ma specjalną logikę do obsługi zaproszeń Twojej aplikacji. To nie zadziała bez partnerstwa między Twoją organizacją a inną aplikacją i prawdopodobnie nie jest rozwiązaniem dla mniejszych organizacji. To powiedziawszy, niektóre aplikacje mogą publicznie dokumentować swoje zachowanie w zakresie uniwersalnych/głębokich linków. Zaimplementujemy fikcyjną wersję tego w naszej próbce.
Najpierw zdefiniuj typ zawartości zaproszenia, który obejmuje tylko informacje zawarte w zaproszeniu i nie zawiera żadnych funkcji. W ten sposób możesz zacząć od typów danych i pomyśleć o swoim kodzie pod kątem tego, jak łączy te dane.
Szybki
/// The content within an invite, with optional fields to accommodate all presenters. /// This type could be modified to also include an image, for sending invites over email. struct InviteContent { /// The subject of the message. Not used for invites without subjects, like text message invites. var subject: String? /// The body of the message. Indispensable content should go here. var body: String? /// The URL containing the invite. In link-copy cases, only this field will be used. var link: URL }
Cel C
/// The content within an invite, with optional fields to accommodate all presenters. /// This type could be modified to also include an image, for sending invites over email. @interface InviteContent : NSObject <NSCopying> /// The subject of the message. Not used for invites without subjects, like text message invites. @property (nonatomic, readonly, nullable) NSString *subject; /// The body of the message. Indispensable content should go here. @property (nonatomic, readonly, nullable) NSString *body; /// The URL containing the invite. In link-copy cases, only this field will be used. @property (nonatomic, readonly) NSURL *link; - (instancetype)initWithSubject:(nullable NSString *)subject body:(nullable NSString *)body link:(NSURL *)link NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end
Kotlin+KTX
/** * The content of an invitation, with optional fields to accommodate all presenters. * This type could be modified to also include an image, for sending invites over email. */ data class InviteContent( /** The subject of the message. Not used for invites without subjects, like SMS. */ val subject: String?, /** The body of the message. Indispensable content should go here. */ val body: String?, /** The URL containing the link to invite. In link-copy cases, only this field will be used. */ val link: Uri )
Java
/** * The content of an invitation, with optional fields to accommodate all presenters. * This type could be modified to also include an image, for sending invites over email. */ public class InviteContent { /** * The subject of the message. Not used for invites without subjects, like SMS. **/ @Nullable public final String subject; /** * The body of the message. Indispensable content should go here. **/ @Nullable public final String body; /** * The URL containing the link to invite. In link-copy cases, only this field will be used. **/ @NonNull public final Uri link; public InviteContent(@Nullable String subject, @Nullable String body, @NonNull Uri link) { // ... } }
Jedynym wymaganym elementem danych jest adres URL, bez którego nie możesz zaprosić użytkowników do swojej aplikacji. Inne fragmenty danych są wyraźnie skonstruowane pod kątem wysyłania e-maili, co czyni je trochę niezręcznymi w niektórych innych przypadkach - podczas wysyłania zaproszenia w wiadomości tekstowej notatka towarzysząca linkowi może brzmieć podobnie do tematu wiadomości e-mail, ale podczas udostępniania w mediach społecznościowych towarzyszący tekst łącza może bardziej przypominać treść wiadomości e-mail. Będziesz musiał sam z tym poeksperymentować, aby znaleźć najlepszą równowagę dla swojej aplikacji, a jeśli nie masz pewności, zawsze możesz skorzystać z usługi, takiej jak Zdalna konfiguracja , aby umożliwić zmianę wartości tekstowych po uruchomieniu aplikacji.
Szybki
/// A type responsible for presenting an invite given using a specific method /// given the content of the invite. protocol InvitePresenter { /// The name of the presenter. User-visible. var name: String { get } /// An icon representing the invite method. User-visible. var icon: UIImage? { get } /// Whether or not the presenter's method is available. iOS devices that aren't phones /// may not be able to send texts, for example. var isAvailable: Bool { get } /// The content of the invite. Some of the content type's fields may be unused. var content: InviteContent { get } /// Designated initializer. init(content: InviteContent, presentingController: UIViewController) /// This method should cause the presenter to present the invite and then handle any actions /// required to complete the invite flow. func sendInvite() }
Cel C
/// A type responsible for presenting an invite given using a specific method /// given the content of the invite. @protocol InvitePresenter <NSObject> /// The name of the presenter. User-visible. @property (nonatomic, readonly) NSString *name; /// An icon representing the invite method. User-visible. @property (nonatomic, readonly, nullable) UIImage *icon; /// Whether or not the presenter's method is available. iOS devices that aren't phones /// may not be able to send texts, for example. @property (nonatomic, readonly) BOOL isAvailable; /// The content of the invite. Some of the content type's fields may be unused. @property (nonatomic, readonly) InviteContent *content; /// Designated initializer. - (instancetype)initWithContent:(InviteContent *)content presentingViewController:(UIViewController *)controller; /// This method should cause the presenter to present the invite and then handle any actions /// required to complete the invite flow. - (void)sendInvite; @end
Kotlin+KTX
/** * Presents the invite using a specific method, such as email or social. */ open class InvitePresenter( /** The user-visible name of the invite method, like 'Email' or 'SMS' */ val name: String, /** An icon representing the invite method. */ @param:DrawableRes @field:DrawableRes val icon: Int, /** Whether or not the method is available on this device. For example, SMS is phone only. */ val isAvailable: Boolean, /** The Content of the invitation */ val content: InviteContent ) { /** * Send the invitation using the specified method. */ open fun sendInvite(context: Context) { // ... } }
Java
/** * Presents the invite using a specific method, such as email or social. */ public class InvitePresenter { /** * The user-visible name of the invite method, like 'Email' or 'SMS' **/ public final String name; /** * An icon representing the invite method. **/ @DrawableRes public final int icon; /** * Whether or not the method is available on this device. For example, SMS is phone only. **/ public final boolean isAvailable; /** * The Content of the invitation **/ public final InviteContent content; public InvitePresenter(String name, @DrawableRes int icon, boolean isAvailable, InviteContent content) { // ... } /** * Send the invitation using the specified method. */ public void sendInvite(Context context) { // ... } }
Teraz pozostaje tylko podłączyć to do wybranego komponentu interfejsu użytkownika. Aby zapoznać się z pełną implementacją tego przepływu zaproszeń, zobacz przykłady w witrynie GitHub dla systemów iOS i Android .
Są to wszystkie metody umożliwiające użytkownikom wysyłanie zaproszeń do znajomych, co jest najlżejszym rozwiązaniem w zakresie zaproszeń. Wiele popularnych aplikacji dostarcza również zaproszenia, wysyłając wiadomości e-mail za pośrednictwem własnego zaplecza, co wymaga zintegrowania usługi wysyłania poczty, ale oferuje szereg korzyści, które nie są dostępne w inny sposób, z kilkoma drobnymi wadami.
Plusy:
- Włącza e-maile ze złożonymi znacznikami, których użytkownik nie może modyfikować przed wysłaniem.
- Umożliwia bardziej szczegółowe śledzenie/analizę (tj. wysyłanie sukcesów i niepowodzeń na backend).
Cons:
- Wiadomości e-mail są częściej oznaczane jako spam
- Wymaga integracji z usługą dostarczania poczty e-mail
- Wymaga uprawnień do kontaktów w aplikacji
Ogólnie rzecz biorąc, wysyłanie zaproszeń za pośrednictwem własnej usługi dostarczania wiadomości e-mail zapewnia bardziej spójne i potencjalnie bogatsze wrażenia z zaproszeń kosztem wszechstronności.
Otwórz połączoną zawartość w swojej aplikacji
Na koniec musisz otrzymać link przekazany do Twojej aplikacji, aby móc wyświetlić zawartość, do której prowadzi link, odbiorcy. Jest to łatwe dzięki pakietowi Dynamic Links SDK:
iOS
W systemie iOS łącze dynamiczne można uzyskać, implementując metodę application:continueUserActivity:restorationHandler:
:. W procedurze obsługi przywracania można uzyskać łącze dynamiczne, wywołując handleUniversalLink:completion:
. Jeśli link dynamiczny został przekazany do Twojej aplikacji, możesz go pobrać z właściwości url
elementu FIRDynamicLink
. Na przykład:
Cel C
[[FIRDynamicLinks dynamicLinks]
handleUniversalLink:userActivity.webpageURL
completion:^(FIRDynamicLink * _Nullable dynamicLink,
NSError * _Nullable error) {
NSString *link = dynamicLink.url;
BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
// ...
}];
Szybki
FIRDynamicLinks.dynamicLinks()?.handleUniversalLink(userActivity.webpageURL!) { (dynamiclink, error) in
let link = dynamicLink.url
let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
// ...
}
Dodatkowo musisz wywołać metodę dynamicLinkFromCustomSchemeURL:
w application:openURL:options:
aby otrzymywać linki dynamiczne przekazywane do Twojej aplikacji jako niestandardowe adresy URL schematów. Na przykład:
Cel C
FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
if (dynamicLink) {
NSString *link = dynamicLink.url;
BOOL strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong;
// ...
return YES;
}
Szybki
let dynamicLink = FIRDynamicLinks.dynamicLinks()?.dynamicLinkFromCustomSchemeURL(url)
if let dynamicLink = dynamicLink {
let link = dynamicLink.url
let strongMatch = dynamicLink.matchConfidence == FIRDynamicLinkMatchConfidenceStrong
// ...
return true
}
Teraz, gdy masz wartość parametru link
, możesz wyświetlić treść, do której prowadzi link, odbiorcy lub przetworzyć dane określone przez parametr w inny sposób. W tym zadaniu może pomóc biblioteka routingu adresów URL, taka jak JLRoutes .
Jeśli otrzymujesz łącze przeznaczone dla określonego odbiorcy, przed uruchomieniem jakiejkolwiek logiki specyficznej dla użytkownika upewnij się, że pewność dopasowania łącza dynamicznego jest strong
.
Android
W systemie Android używasz metody getDynamicLink()
do pobierania danych z łącza dynamicznego:
Kotlin+KTX
Firebase.dynamicLinks .getDynamicLink(intent) .addOnCompleteListener { task -> if (!task.isSuccessful) { // Handle error // ... } val invite = FirebaseAppInvite.getInvitation(task.result) if (invite != null) { // Handle invite // ... } }
Java
FirebaseDynamicLinks.getInstance() .getDynamicLink(getIntent()) .addOnCompleteListener(new OnCompleteListener<PendingDynamicLinkData>() { @Override public void onComplete(@NonNull Task<PendingDynamicLinkData> task) { if (!task.isSuccessful()) { // Handle error // ... } FirebaseAppInvite invite = FirebaseAppInvite.getInvitation(task.getResult()); if (invite != null) { // Handle invite // ... } } });
Teraz, gdy masz wartość parametru link
, możesz wyświetlić treść, do której prowadzi link, odbiorcy lub przetworzyć dane określone przez parametr w inny sposób. W tym zadaniu może pomóc biblioteka routingu adresów URL.