Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/firebase_in_app_messaging/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 0.0.1

* Initial release
27 changes: 27 additions & 0 deletions packages/firebase_in_app_messaging/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15 changes: 15 additions & 0 deletions packages/firebase_in_app_messaging/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Firebase In-App Messaging

[![pub package](https://img.shields.io/pub/v/firebase_app_messaging.svg)](https://pub.dartlang.org/packages/firebase_app_messaging)

A Flutter plugin to use the [Firebase App Messaging API](https://firebase.google.com/products/in-app-messaging/).

*Note*: This plugin is still under development, and some APIs might not be available yet. [Feedback](https://github.com/flutter/flutter/issues) and [Pull Requests](https://github.com/flutter/plugins/pulls) are most welcome!

## Usage

To use this plugin, add `firebase_app_messaging` as a [dependency in your pubspec.yaml file](https://flutter.io/platform-plugins/). You must also configure firebase dynamic links for each platform project: Android and iOS (see the example folder or https://codelabs.developers.google.com/codelabs/flutter-firebase/#4 for step by step details).

## Getting Started

See the `example` directory for a complete sample app using Firebase App Messaging.
37 changes: 37 additions & 0 deletions packages/firebase_in_app_messaging/android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
group 'io.flutter.plugins.firebaseappmessaging'
version '1.0-SNAPSHOT'

buildscript {
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
}
}

rootProject.allprojects {
repositories {
google()
jcenter()
}
}

apply plugin: 'com.android.library'

android {
compileSdkVersion 27

defaultConfig {
minSdkVersion 16
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
dependencies {
api 'com.google.firebase:firebase-app-messaging:16.1.2'
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx1536M
1 change: 1 addition & 0 deletions packages/firebase_in_app_messaging/android/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'firebase_app_messaging'
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.flutter.plugins.firebasedynamiclinks">

<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
package io.flutter.plugins.firebasedynamiclinks;

import android.net.Uri;
import android.support.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.dynamiclinks.DynamicLink;
import com.google.firebase.dynamiclinks.FirebaseDynamicLinks;
import com.google.firebase.dynamiclinks.PendingDynamicLinkData;
import com.google.firebase.dynamiclinks.ShortDynamicLink;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** FirebaseDynamicLinksPlugin */
public class FirebaseDynamicLinksPlugin implements MethodCallHandler {
private Registrar registrar;

private FirebaseDynamicLinksPlugin(Registrar registrar) {
this.registrar = registrar;
}

public static void registerWith(Registrar registrar) {
final MethodChannel channel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_dynamic_links");
channel.setMethodCallHandler(new FirebaseDynamicLinksPlugin(registrar));
}

@Override
public void onMethodCall(MethodCall call, Result result) {
switch (call.method) {
case "DynamicLinkParameters#buildUrl":
DynamicLink.Builder urlBuilder = setupParameters(call);
result.success(urlBuilder.buildDynamicLink().getUri().toString());
break;
case "DynamicLinkParameters#buildShortLink":
DynamicLink.Builder shortLinkBuilder = setupParameters(call);
buildShortDynamicLink(shortLinkBuilder, call, createShortLinkListener(result));
break;
case "DynamicLinkParameters#shortenUrl":
DynamicLink.Builder builder = FirebaseDynamicLinks.getInstance().createDynamicLink();

Uri url = Uri.parse((String) call.argument("url"));
builder.setLongLink(url);
buildShortDynamicLink(builder, call, createShortLinkListener(result));
break;
case "FirebaseDynamicLinks#retrieveDynamicLink":
handleRetrieveDynamicLink(result);
break;
default:
result.notImplemented();
break;
}
}

private void handleRetrieveDynamicLink(final Result result) {
FirebaseDynamicLinks.getInstance()
.getDynamicLink(registrar.activity().getIntent())
.addOnCompleteListener(
registrar.activity(),
new OnCompleteListener<PendingDynamicLinkData>() {
@Override
public void onComplete(@NonNull Task<PendingDynamicLinkData> task) {
if (task.isSuccessful()) {
PendingDynamicLinkData data = task.getResult();
if (data != null) {
Map<String, Object> dynamicLink = new HashMap<>();
dynamicLink.put("link", data.getLink().toString());

Map<String, Object> androidData = new HashMap<>();
androidData.put("clickTimestamp", data.getClickTimestamp());
androidData.put("minimumVersion", data.getMinimumAppVersion());

dynamicLink.put("android", androidData);
result.success(dynamicLink);
return;
}
}
result.success(null);
}
});
}

private OnCompleteListener<ShortDynamicLink> createShortLinkListener(final Result result) {
return new OnCompleteListener<ShortDynamicLink>() {
@Override
public void onComplete(@NonNull Task<ShortDynamicLink> task) {
if (task.isSuccessful()) {
Map<String, Object> url = new HashMap<>();
url.put("url", task.getResult().getShortLink().toString());

List<String> warnings = new ArrayList<>();
for (ShortDynamicLink.Warning warning : task.getResult().getWarnings()) {
warnings.add(warning.getMessage());
}
url.put("warnings", warnings);

result.success(url);
} else {
Exception exception = task.getException();
String errMsg = "Unable to create short link";
if (exception != null && exception.getLocalizedMessage() != null) {
errMsg = exception.getLocalizedMessage();
}
result.error("short_link_error", errMsg, null);
}
}
};
}

private void buildShortDynamicLink(
DynamicLink.Builder builder, MethodCall call, OnCompleteListener<ShortDynamicLink> listener) {
Integer suffix = null;

Map<String, Object> dynamicLinkParametersOptions =
call.argument("dynamicLinkParametersOptions");
if (dynamicLinkParametersOptions != null) {
Integer shortDynamicLinkPathLength =
(Integer) dynamicLinkParametersOptions.get("shortDynamicLinkPathLength");
if (shortDynamicLinkPathLength != null) {
switch (shortDynamicLinkPathLength) {
case 0:
suffix = ShortDynamicLink.Suffix.UNGUESSABLE;
break;
case 1:
suffix = ShortDynamicLink.Suffix.SHORT;
break;
default:
break;
}
}
}

if (suffix != null) {
builder.buildShortDynamicLink(suffix).addOnCompleteListener(listener);
} else {
builder.buildShortDynamicLink().addOnCompleteListener(listener);
}
}

private DynamicLink.Builder setupParameters(MethodCall call) {
DynamicLink.Builder dynamicLinkBuilder = FirebaseDynamicLinks.getInstance().createDynamicLink();

String domain = call.argument("domain");
String link = call.argument("link");

dynamicLinkBuilder.setDynamicLinkDomain(domain);
dynamicLinkBuilder.setLink(Uri.parse(link));

Map<String, Object> androidParameters = call.argument("androidParameters");
if (androidParameters != null) {
String packageName = valueFor("packageName", androidParameters);
String fallbackUrl = valueFor("fallbackUrl", androidParameters);
Integer minimumVersion = valueFor("minimumVersion", androidParameters);

DynamicLink.AndroidParameters.Builder builder =
new DynamicLink.AndroidParameters.Builder(packageName);

if (fallbackUrl != null) builder.setFallbackUrl(Uri.parse(fallbackUrl));
if (minimumVersion != null) builder.setMinimumVersion(minimumVersion);

dynamicLinkBuilder.setAndroidParameters(builder.build());
}

Map<String, Object> googleAnalyticsParameters = call.argument("googleAnalyticsParameters");
if (googleAnalyticsParameters != null) {
String campaign = valueFor("campaign", googleAnalyticsParameters);
String content = valueFor("content", googleAnalyticsParameters);
String medium = valueFor("medium", googleAnalyticsParameters);
String source = valueFor("source", googleAnalyticsParameters);
String term = valueFor("term", googleAnalyticsParameters);

DynamicLink.GoogleAnalyticsParameters.Builder builder =
new DynamicLink.GoogleAnalyticsParameters.Builder();

if (campaign != null) builder.setCampaign(campaign);
if (content != null) builder.setContent(content);
if (medium != null) builder.setMedium(medium);
if (source != null) builder.setSource(source);
if (term != null) builder.setTerm(term);

dynamicLinkBuilder.setGoogleAnalyticsParameters(builder.build());
}

Map<String, Object> iosParameters = call.argument("iosParameters");
if (iosParameters != null) {
String bundleId = valueFor("bundleId", iosParameters);
String appStoreId = valueFor("appStoreId", iosParameters);
String customScheme = valueFor("customScheme", iosParameters);
String fallbackUrl = valueFor("fallbackUrl", iosParameters);
String ipadBundleId = valueFor("ipadBundleId", iosParameters);
String ipadFallbackUrl = valueFor("ipadFallbackUrl", iosParameters);
String minimumVersion = valueFor("minimumVersion", iosParameters);

DynamicLink.IosParameters.Builder builder = new DynamicLink.IosParameters.Builder(bundleId);

if (appStoreId != null) builder.setAppStoreId(appStoreId);
if (customScheme != null) builder.setCustomScheme(customScheme);
if (fallbackUrl != null) builder.setFallbackUrl(Uri.parse(fallbackUrl));
if (ipadBundleId != null) builder.setIpadBundleId(ipadBundleId);
if (ipadFallbackUrl != null) builder.setIpadFallbackUrl(Uri.parse(ipadFallbackUrl));
if (minimumVersion != null) builder.setMinimumVersion(minimumVersion);

dynamicLinkBuilder.setIosParameters(builder.build());
}

Map<String, Object> itunesConnectAnalyticsParameters =
call.argument("itunesConnectAnalyticsParameters");
if (itunesConnectAnalyticsParameters != null) {
String affiliateToken = valueFor("affiliateToken", itunesConnectAnalyticsParameters);
String campaignToken = valueFor("campaignToken", itunesConnectAnalyticsParameters);
String providerToken = valueFor("providerToken", itunesConnectAnalyticsParameters);

DynamicLink.ItunesConnectAnalyticsParameters.Builder builder =
new DynamicLink.ItunesConnectAnalyticsParameters.Builder();

if (affiliateToken != null) builder.setAffiliateToken(affiliateToken);
if (campaignToken != null) builder.setCampaignToken(campaignToken);
if (providerToken != null) builder.setProviderToken(providerToken);

dynamicLinkBuilder.setItunesConnectAnalyticsParameters(builder.build());
}

Map<String, Object> navigationInfoParameters = call.argument("navigationInfoParameters");
if (navigationInfoParameters != null) {
Boolean forcedRedirectEnabled = valueFor("forcedRedirectEnabled", navigationInfoParameters);

DynamicLink.NavigationInfoParameters.Builder builder =
new DynamicLink.NavigationInfoParameters.Builder();

if (forcedRedirectEnabled != null) builder.setForcedRedirectEnabled(forcedRedirectEnabled);

dynamicLinkBuilder.setNavigationInfoParameters(builder.build());
}

Map<String, Object> socialMetaTagParameters = call.argument("socialMetaTagParameters");
if (socialMetaTagParameters != null) {
String description = valueFor("description", socialMetaTagParameters);
String imageUrl = valueFor("imageUrl", socialMetaTagParameters);
String title = valueFor("title", socialMetaTagParameters);

DynamicLink.SocialMetaTagParameters.Builder builder =
new DynamicLink.SocialMetaTagParameters.Builder();

if (description != null) builder.setDescription(description);
if (imageUrl != null) builder.setImageUrl(Uri.parse(imageUrl));
if (title != null) builder.setTitle(title);

dynamicLinkBuilder.setSocialMetaTagParameters(builder.build());
}

return dynamicLinkBuilder;
}

private static <T> T valueFor(String key, Map<String, Object> map) {
@SuppressWarnings("unchecked")
T result = (T) map.get(key);
return result;
}
}
8 changes: 8 additions & 0 deletions packages/firebase_in_app_messaging/example/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: f408bb06f9361793ca85493c38d809ee1e2f7e30
channel: master
12 changes: 12 additions & 0 deletions packages/firebase_in_app_messaging/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# firebase_dynamic_links_example

Demonstrates how to use the firebase_dynamic_links plugin.

## *Important*

The example app for this plugin only receives links on Android. Xcode has signing requirements that must be configured with an iOS app developer team id. Check the `firebase_dynamic_links/README.md` for more details.

## Getting Started

For help getting started with Flutter, view our online
[documentation](https://flutter.io/).
Loading