This repository contains the Uni Links plugin platform interface, as well as platform specific implementations.
The main uni_links
plugin source code and documantation can be found in the uni_links directory.
Flutter plugin for accepting incoming links.
License: BSD 2-Clause "Simplified" License
This repository contains the Uni Links plugin platform interface, as well as platform specific implementations.
The main uni_links
plugin source code and documantation can be found in the uni_links directory.
We tried Universal links with https and it worked on our IOS devices but using Custom Schema didn't work on all app states ex foreground, background and suspended.
Appreciate your support
Describe the bug
getUriLinksStream().listen((Uri uri) {
}, onError: (err) {
});
} on PlatformException {
// Handle exception by warning the user their action did not succeed
// return?
}
this method is invoked twice everytime the app is being called by scheme
I am using custom deep linking, not associated one..
To Reproduce
Steps to reproduce the behavior:
Expected behavior
code invoked once should be expected
Smartphone (please complete the following information):
iOS iphone XS Max simulator iOS 12
Additional context
my code snipset as below:
Future initUniLinks() async {
try {
String initialLink = await getInitialLink();
getUriLinksStream().listen((Uri uri) {
Map<String, String> query = uri.queryParameters;
Map<String, dynamic> json = jsonDecode(query['json']);
DeepLinkDao deepLinkDao = DeepLinkDao.fromJson(json);
handleDeepLink(deepLinkDao);
}, onError: (err) {
var a = 1;
var b = a + 1;
});
} on PlatformException {
// Handle exception by warning the user their action did not succeed
// return?
}
}
I'm using custom scheme and am testing on my iPad which is running iOS.
Running any code such as:
/usr/bin/xcrun simctl openurl xxxYYY999 "unilinks://host/path/subpath"
returns Invalid device: xxxYYY999
The id xxxYYY999 is what "flutter devices" returns as well as xcode devices and simulators.
What is the difference between UriLinks and Links?
As I understand it similar URL scheme architecture exists for desktops.
I am playing around with flutter desktop and would like to get uni links working for it. I think it is possible.
The main obstacle is getting good doc for Mac OS and Windows and Linux.
So my request is for more high quality info / links for how each platform does this.
The flutter desktop plugins API is usable now ( just went through a refactoring ).
i get uri when click link from gmail, skype, slack success. Button when i click url from facebook app, i can't get uri
I am using this tutorial to implement the plugin
https://peb.si/deep-links-flutter/
and it works perfectly with andriod, However, on ios the link does not direct me to the screen that I want to be displayed if the parameters matches the values that I have inserted in the method :
void handleLink(Uri link) {
var parameters = link.pathSegments;
// we now have the parameters object to work with and can check the path segments!
// e.g if we're sending https://peb.si/inbox/1 meaning 'open conversation #1' we can handle it like this:
if (parameters[0] == "inbox" && parameters[1] != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatPage(
id: int.parse(parameters[1]))));
}
}
and it just direct me to the home screen of the app instead.
How Can I solve this issue?!
Thanks in advance :)
I'm using https scheme and am testing on my Android Emulator, which is running Android 9.0.
The getLatestLink method isn't implemented on android:
https://github.com/avioli/uni_links/blob/master/android/src/main/java/name/avioli/unilinks/UniLinksPlugin.java#L69
@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getInitialLink")) {
result.success(initialLink);
// } else if (call.method.equals("getLatestLink")) {
// result.success(latestLink);
} else {
result.notImplemented();
}
}
It appears that this code has been commented out since inception of the file.
Is there a technical reason this cannot be enabled?
Both for Android and for IOS, I get this:
"Unhandled exception:
NoSuchMethodError: The getter 'host' was called on null
It appears in the verbose log.
Can I check somehow the way the application was started and then use the corresponding method?
When using Universal link in IOS the listener getUriLinksStream
is receiving the the link correctly, but getInitialUri
is not reiceving it. Any idea and what could cause this issue?
I can get uri from getUriLinksStream, but if the app launchs directly, the call doesn't return
Hi there,
if you install url_launcher
and uni_links
and open up a stream to uni.getUriLinksStream().listen(print);
and then url.launch("https://myserver/myredirect")
which redirects to a scheme, such as myscheme:/?payload="foo"
, you will see the browser disappear (as expected) but no event is recoreded by uni_links
. However, if you open your browser manually, and type myscheme:/?payload="foo"
in the address bar, it will open the app and uni_links
will fire the event to console.
Short version: if you're using uni_links
to listen for oauth2 redirects, the events do not fire. But if you use it any other way, it seems to work.
Do you have any suggestions for listening for these events?
getUriLinksStream It doesn't work under IOS and won't receive monitoring results.
Your library is really good its working fine when app creates a new instance while entering to the app through deep link but in my case when app existing in the background if i entered that app through some uri by deepLinking the getInitialUri() not fetching that url.
I'm using https scheme and am testing
on my Samsung S4,
which is running Android 5.0.1.
I am getting:
MissingPluginException(No implementation found for method listen on channel uni_links/events)
I get this when trying to call getLinksStream, getInitalLink or any uni_links platform method.
I'm using custom scheme and am testing
on my Google Pixel 2,
which is running the Android Q beta (but this is unrelated).
In my main() method, I've registed my getUriLinksStream()
to navigate to a specific Page, SuccessPage, after my one and only deeplink comes through. This works on its own, but now I introduce the scenario where my LoginPage is opening up a browser through url_launcher for an OAuth2 flow, then when the deeplink comes back, there's a brief moment for which the LoginPage attempts to rebuild, and then when the Navigator comes along, I get an exception saying setState() or markNeedsBuild() called during build
, because they're both interfering. How do I stop them from executing too quickly? Can I delay the stream action somehow?
Describe the bug
When build app with this plugin for ios, a buildtime show 2 warnings:
UniLinksPlugin.h:4:4: pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified) [-Wnullability-completeness]
Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)
UniLinksPlugin.h:7:33: block pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified) [-Wnullability-completeness]
Block pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)
Posible solutions generated for XCode
For two cases:
Smartphone (please complete the following information):
Additional context
This error happend in XCode build and in Codemagic.
I'm using a printer app that gets called from flutter print://somepath, then the printer app calls myapp://anotherpath, and then later my app calls print://yetanotherpath, and the printer app calls myapp://anewpath.
On the second call to my app, anewpath appears insdie getUriLinksStream().listen() which at some point calls Navigator.pushReplacementNamed and exits the function unexpectedly, so that no code after that will run. I haven't been able to see any exceptions since my device is connected to the printer when this error occurs.
Note that the first call to my app, anotherpath is treated exactly the same as anewpath, however without the bug appearing.
Expected behavior
The expected behavior is that Navigator.pushReplacementNamed works, and any code after that runs.
Smartphone (please complete the following information):
Additional context
Also note that this bug only happens on iOS, on an old iPad that I've been working with. The problem does not happen on my android devices, though on the android devices getUrlLinksStream isn't used because getInitialUri() actually works on them. getInitialUri() never works on this iPad.
Describe the bug
When I tried to use "https" for deep link working on android and iOS not working. Then I tried "unilinks" its working both. But sharing unilinks via sms not clickable. So I want to use "https" for deep linking
To Reproduce
I tried the scheme as "https" like below, its working on ANDROID and not working iOS. For iOS I already added "https://skillsdoctor.net/apple-app-site-association". still "https" not working.
IOS :
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>skillsdoctor.net</string>
<key>CFBundleURLSchemes</key>
<array>
<string>https</string>
</array>
</dict>
</array>
ANDROID
<!-- Deep Links -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="skillsdoctor.net" />
</intent-filter>
<!-- App Links -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="skillsdoctor.net" />
</intent-filter>
Expected behavior
Either https/unilinks deep link should work on both platform.
why in the example does uni_links get specified under dev_dependencies instead of dependencies? i would think it would be the opposite. just wanting to confirm -- thanks.
The title says it all. Now that flutter started supporting macOS, it would be create if this plugin also worked for it. (Or at least doesn't make the platform channel calls fail.)
I'm using https scheme
and am testing on my Android Phone which is running Android 9.
I registered the .well-known/assetlinks.json
in my domain.
Running the following from a local shell works fine and hits the callback within the app:
adb shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://xxxxx.app/?code=123"'
BUT when an OAuth window redirects to https://xxxxx.app/?code=123
nothing happens.
Manually putting the https://xxxxx.app/?code=123
into the local browser only opens the website but does not open the App on my test phone, or when it already runs it does not hit the callback.
What can I do?
In your readme it states:
// NOTE: Necessary, until Flutter supports
//application:continueUserActivity:restorationHandler
within the
//FlutterPlugin
protocol.
I can see that Flutter now supports this callback: https://docs.flutter.io/objcdoc/Protocols/FlutterPlugin.html#/c:objc(pl)FlutterPlugin(im)application:continueUserActivity:restorationHandler:
Do we still need to add the ios related code?
I'm using https scheme and am testing on my Google Pixelbook, which is running Chrome OS v73.0.3683.88.
I am unable to get the app to open in response to a link when it is running on Chrome OS.
I'm not sure this issue necessarily falls in the scope of this library, but I imagine it is not super hard to fix. I have found what I think is a related issue for React Native, but I am new to developing Android apps, so at the moment I am not able to figure out the right way to trigger/handle the intent.
Universal Links was working fine on iOS 12 but I ran into issues iOS 13.+
URLs that's supposed to open the app when tapped are just opening up in the browser and redirect to app store.
Please update possible solution ASAP.
I have an app and until now two users reported that they aren't able to login (My app uses uni_links to get the response from OAuth).
after sending these users a custom build to debug the issue via sentry, I found that they were getting the getInitialLink as null.
In the majority of the userbase the app and uni_links works just fine (~10k users).
What I could find that these users share is that they are on Android and that the link was being called from chrome.
I wasn't able to find a way to reproduce the bug properly in my setup.
All that I could find out until now is that they use other apps that uses deeplinks (non flutter apps) and they work properly.
the pattern that I'm using right now for my app is
luzinha://login?code=########################
Hello guys! I have a set of custom URL schemes that are triggered with push notifications.
Everything works fine with Android on all states (Open, Foreground/Background, Closed/Forced Quit). But not with iOS, which does not work when app is closed.
Everytime i close the app, force to open with a custom URL scheme, the app opens but the getInitialUri returns the uri as null, which is being called here:
main.dev
StreamSubscription uriSubscription;
@override
void initState() {
super.initState();
initPlatformState();
}
@override
void dispose() {
if (uriSubscription != null) {
uriSubscription.cancel();
}
super.dispose();
}
Future<void> initPlatformState() async {
debugPrint('com.fonixtelematics.app: initPlatformState');
// if (!mounted) return;
if (uriSubscription != null) {
uriSubscription.cancel();
}
await pushService.init();
uriSubscription = await URILinks().initStream();
await URILinks().checkInitialURI();
}
urilinks.dart
class URILinks {
Future<StreamSubscription> initStream() async {
return getUriLinksStream().listen(uriLinksHandler);
}
Future<void> checkInitialURI() async {
debugPrint('com.fonixtelematics.app: checkInitialURI');
return getInitialUri().then(uriLinksHandler).catchError((e) {
debugPrint(
'com.fonixtelematics.app: checkInitialURI ERROR ' + e.toString());
navigatorKey.currentState.pushNamed(Routes.main);
});
}
void uriLinksHandler(Uri uri) {
debugPrint('com.fonixtelematics.app: uriLinksHandler ' + uri.toString());
if (uri != null) {
debugPrint('com.fonixtelematics.app: uriLinksHandler ' + uri.host);
}
if (uri != null && uri.host != null && uri.host.isNotEmpty) {
switch (uri.host) {
case 'auth':
...
break;
case 'alert':
...
break;
default:
navigatorKey.currentState.pushNamed(Routes.main);
break;
}
} else {
throw (false);
}
}
}
Is anyone else having the same issue?
I'm using unilinks and am testing
on my iOS Simulator
which is running iOS 13.
When i execute the command: ▶ /usr/bin/xcrun simctl openurl booted "lejour://profile"
i got this error: An error was encountered processing the command (domain=NSOSStatusErrorDomain, code=-10814):
The operation couldn’t be completed. (OSStatus error -10814.)
I wanna know if have any way to catch this error and redirect to app store or play store in app page
I'm using android with flutter 1.7.8 and uni_links 0.2.0.
I added an intent to my android manifest to register deep links:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="shopli"/>
Now when I test this by using the adb shell and call:
am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "shopli://shopli.sveri.de/d8c9e9a9-a04c-4c8c-aa68-104124333c8f"
my app is being notified and acts on it as expected.
But let's say I receive this link via email / messenger clicking on the link will open the browser which then tries to load shopli.sveri.de. I would expect it to open my app instead.
Am I missing something here?
Hi,
I wonder why the distinction was made between receiving values in the background and foreground.
Now you have to check if the initial deeplink was not null.
final initialLink = await getInitialLink();
if (initialLink != null) {
...
}
As well as also listen on the stream when a deeplink was received in the foreground.
getLinksStream().listen(...)
We implemented a simple wrapper inside our app which deals with this.
Only exposes 1 stream where all events are posted including the initial one.
I wondered if it was something you'd be interested in to include in the lib already?
The helper class itself.
import 'dart:async';
import 'package:rxdart/rxdart.dart';
import 'package:uni_links/uni_links.dart';
/// Adds a wrapper around the uni_links library.
class DeepLinkHelper {
StreamSubscription<String> _deepLinkStreamSubscription;
final BehaviorSubject<String> _deepLinkSink = BehaviorSubject();
Stream<String> get deepLinkStream => _deepLinkSink.stream;
DeepLinkHelper() {
_postInitialLink();
_deepLinkStreamSubscription = getLinksStream().listen(_deepLinkSink.add);
}
void _postInitialLink() async {
try {
final initialLink = await getInitialLink();
if (initialLink != null) {
_deepLinkSink.add(initialLink);
}
} finally {}
}
void dispose() {
_deepLinkStreamSubscription.cancel();
}
}
I'm using https scheme and am testing
on my Android Emulator, which is running Android 6: Marshmallow.
They key thing is, I can get the _latestLink to change if it is everything else besides res['message']['access_token'], even res['status'].toString work, which is here in this example...
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:uni_links/uni_links.dart';
import 'package:http/http.dart' as http;
import 'package:url_launcher/url_launcher.dart';
import 'dart:convert';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
String _latestLink = "";
StreamSubscription _sub;
final _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
initState() {
super.initState();
initPlatformState();
}
@override
dispose() {
if (_sub != null) _sub.cancel();
super.dispose();
}
// Platform messages are asynchronous, so we initialize in an async method.
initPlatformState() async {
await initPlatformStateForStringUniLinks();
}
initPlatformStateForStringUniLinks() async {
_sub = getLinksStream().listen((String link) async {
if (!mounted) return;
if(RegExp(r'(?<=authorization_token=)(.*)(?=$)').hasMatch(link)) {
var res = await getToken(link);
print(res);
if(res['status']){
setState(() {
_latestLink = res['status'].toString();
try {
} on FormatException {}
});
}
}
}, onError: (err) {
if (!mounted) return;
});
if (!mounted) return;
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
key: _scaffoldKey,
body: new ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(8.0),
children: <Widget>[
new ListTile(
title: const Text('Link'),
subtitle: new Text('$_latestLink'),
),
homeContent()
],
),
),
);
}
}
homeContent(){
return Center(
child: RaisedButton(
onPressed: () async {
const url = 'https://example.com/anotherPath?client_id=<my client id string, not posting here>';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
},
child: Text('Signin'),
)
);
}
getToken(link) async {
var req = await http.get("https://example.com/path?client_id=<my client id string, not posting here>&secret=<my secret string, not posting here>&authorization_token=" + RegExp(r'(?<=authorization_token=)(.*)(?=$)').stringMatch(link));
var res = json.decode(req.body);
return res;
}
This code is actually just the example stripped of things.
Any ideia what I might be doing wrong?
I'm using custom scheme and am testing
on my iOS Simulator
which is running IOS12.1.
Hi, I'm trying to perform an OAuth scenario. I use the package launch_url to open the oauth authorization end point. There I provide my user credentials. Everything works fine. My app gets called back through the redirect uri that use my custom scheme and host but the safari browser stay open on top of the app with a blank page. I need to manually click on the top left corner OK button to close it and see my app. My app is not coming to the foreground with the deep link call back from safari. Any idea on how to resolve this?
Thanks for any help.
Great package thanks for this.
Alex
Good Afternoon.. I worked a few hours to generate an external link to the app. Deep link worked in one app and not in another. After quitting (dawn), I realized that the app that worked did not support androidx. I wonder if this is really what is preventing intents, because Manifest did not recognize intents-filter. Generated a "No Activity found" error. Is this error happening on androidx?
Has anyone been able to get this to work on iOS with Swift enabled?
in android
adb shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "unilinks://example.com/path/portion/?uid=123&token=abc"'
I can get the uid, but I cant not get the token
what's wrong with me?
We are using flutter web, desktop and mobile.
Has anyone gotten this to work with Flutter web ?
I could be wrong but I don't believe this package is setup for AndroidX. Can you please confirm either way?
Describe the bug
It was a long and tedious process to make code working on android also work on ios.
getInitialUri doesn't behave the same, as it's always null on iOS, whereas it always works on android. The workaround for me was to use getUriLinksStream().listen on iOs.
Static variables, such as myClass.myVar inside myfile.dart are forgotten in android when myappscheme://somepath is called from another app, but remembered on iOS.
Expected behavior
For iOS and Android to work the same way.
Logout (auth0.webAuth.clearSession()
) Issues:
If the user is signed in, it will logout the user but it will not return to the app. Instead, it will continue on to the login page on the web browser. And once logged in, it will proceed to the account profile page. Basically it is treated as a normal web session and will never exit the browser and return to the app.
If the user is NOT signed in, it will crash and exit the app, without event throwing errors/exceptions.
Login (auth0.webAuth.authorize()
) Issues:
I'm too lazy to experiment, but have you figured a way to open desired page without opening a home page before it (on all platforms)? Currently, I have home page opening and then the one that I want
not a bug - this package is great. the problem i'm having, as someone who knows zero Swift, is how to support universal links when your Flutter app has Swift support enabled. there is no AppDelegate.m anymore, but rather an AppDelegate.swift. and there is now Runner-Bridging-Header.h instead of main.m and AppDelegate.h.
fyi, the only reason i had to include Swift support in the build is because of package contacts_service.
Hi, I'm having trouble getting the uni_links plugin to provide the URI at startup using getInitialLink. While I can get it to trigger an event using a stream this doesn't work when the app is first open. I'm not sure if its a problem with the plugin or if I'm not doing something right. Could I get some help. I'm not getting any errors. the getInitialLink function is just returning null.
Hey there!
I'm using custom scheme and am testing on iOS Simulator which is:
Version 11.0 (SimulatorApp-912.1 SimulatorKit-570.3 CoreSimulator-681.5.1)
Im trying to navigate to another view, but it is not working, this is the part of the code:
// Attach a second listener to the stream
getUriLinksStream().listen((Uri uri) {
print('got uri: ${uri?.path} ${uri?.queryParametersAll}');
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AcceptInvitation()),
);
}, onError: (err) {
print('got err: $err');
});
The full exception:
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: Navigator operation requested with a context that does not include a Navigator.
The context used to push or pop routes from the Navigator must be that of a widget that is a descendant of a Navigator widget.
#0 Navigator.of.<anonymous closure> (package:flutter/src/widgets/navigator.dart:1475:9)
#1 Navigator.of (package:flutter/src/widgets/navigator.dart:1482:6)
#2 Navigator.push (package:flutter/src/widgets/navigator.dart:1107:22)
#3 _BotAppState.initPlatformStateForUriUniLinks.<anonymous closure> (package:py/main.dart:58:17)
#4 _rootRunUnary (dart:async/zone.dart:1132:38)
#5 _CustomZone.runUnary (dart:async/zone.dart:1029:19)
#6 _CustomZone.runUnaryGuarded (dart:async/zone.dart:931:7)
#7 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:336:11)
#8 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:263:7)
#9 _SinkTransformerStreamSubscription._add (dart:async/strea<…>
Any clue what Im doing wrong?
Thanks!
This is my configuration :
Flutter 1.0.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 5391447fae (3 months ago) • 2018-11-29 19:41:26 -0800
Engine • revision 7375a0f414
Tools • Dart 2.1.0 (build 2.1.0-dev.9.4 f9ebf21297)
In the provided docs only the receiving part is shown, there's no docs of how an app A can start an app B using this library.
I'm using [https scheme] and am testing
on my [iOS Simulator, Android Emulator],
which is running [iOS13.1, Android 10].
Works well on Android. However, doesn't work on iOS. I believe the only thing that sounded weird in the docs was
either through Xcode or by editing (or creating and adding to Xcode) ios/Runner/Runner.entitlements file
What is adding to Xcode? I simply created that XML file and placed it under ios/Runner. Do I need to do anything else in xcode?
How to clear initialLink after redirect to another page?
because after redirect to another page and open previous page, initialLink still have data so redirect to another page again
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.