Not receiving firebase dynamic link - flutter

Currently I am doing a project that calls a secondary app and I launch the 2nd app through InAppWebView. While the 2nd app is facing the user, the inappwebview is still running and sends live update, which I am capturing to trigger events, for example like it will send payment complete, allowing me to trigger to go summary page.
The issue I am having is, I am unable to smoothly transit back to my app. So there are two ways that I found that allow me to go back to the app.
One, launch the URL using my dynamic link but this method I am unable to receive the link.
Second, to launch it through external application like chrome.
The second method works perfectly other than the fact that the screen jumps to chrome. And it continues from where I left off.
However, what I want is both, continue from where I left off and not have the jumping of the chrome. Or from what I have read the right way is to direct to the activity using intent filter. But the smooth method I am not receiving the links but the jump method I am receiving the links.
Please help T - T

if you need to add dynamic links with firebase you can find the setup right in the docs and with the help with firebase_dynamic_links you can handle where to go inside your app and also can execute parameters from the link in the function below you make a stream that listen to any dynamic link clicked while the app in the background or foreground , the PendingDynamicLinkData is when the app terminated. the business logic and how the app interacts ups to you.
static Future<void> initDynamicLink() async {
FirebaseDynamicLinks.instance.onLink.listen((dynamicLink) async {
if (dynamicLink.link != Uri.parse("uri")) {
log(dynamicLink.link.queryParameters.toString());
final Uri deepLink = dynamicLink.link;
// you should handle the navigation or you logic here
}
}).onError((error) {
debugPrint("error from dynamic link Stream : : :: ${error.toString()}");
});
final PendingDynamicLinkData? initialLink =
await FirebaseDynamicLinks.instance.getInitialLink();
try {
if (initialLink != null) {
log(initialLink.link.toString());
final Uri deepLink = dynamicLink.link;
// you should handle the navigation or you logic here
}
} catch (e) {
debugPrint('No deepLink found');
}
}
don't forget to call this function in the main like this
void main()async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
initDynamicLink();
}

Related

Handle terminated state using flutter local notifications & FCM

I'm created a handler for incoming FCM using flutter local notifications & on tap on each notification it can navigate to a specific screen and that working properly as soon as the app in the foreground and background but when the app terminated it navigates me to the home screen instead.
I use FirebaseMessaging.onBackgroundMessage() as a listener in case of background & terminated & FirebaseMessaging.onMessage.listen() in case of background with flutterLocalNotificationsPlugin.show() in both cases
When app is closed, you need to check for the notification that was clicked when the app was opened.
use:
final RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
to get the initial message somewhere while initializing your app and handle it if it is not null
Sometimes you might have to add a short delay to handle it after the rest of your app has been initialized. You can use
Future.delayed(const Duration(milliseconds: 300)).then((value){
// handle it in here
)};
Don't forget to do this after you call
await Firebase.initializeApp();

Flutter: How to get/write data from/to shared preferences from action button's click using Awesome notifications?

I am using Awesome notifications to display notifications in my app. In the notifications, I have an action button, and when pressing it, the app is supposed to read and write some simple data from/to the memory of the phone using shared preferences. This is supposed to happen in the background without opening the app in the foreground.
I tried the following code:
#pragma("vm:entry-point")
static Future<void> onActionReceivedMethod(ReceivedAction action) async {
print('It works');
print(action.toMap());
final SharedPreferences prefs = await SharedPreferences.getInstance();
List<PinnedFolder> pinnedList = [];
try {
final String? pinnedString = prefs.getString('pinnedKey');
if (pinnedString != null) {
pinnedList = PinnedFolder.decode(pinnedString);
print('PinnedList got from memory, length: ${pinnedList.first.pinnedList.length}');
}
} catch (error) {
debugPrint('Error: couldnt get pinned folders: $error');
}
The "It works" and 'action.toMap()' get printed, but I can't get data from shared preferences. Is it so, that I can't use added packages in #pragma("vm:entry-point") functions? What would be the best way to fix the code? The action doesn't need to happen right after the button press, it can also happen the next time when the app is in the foreground, but so that the button action information is still available.
I found a solution using the package flutter_secure_storage.
const storage = FlutterSecureStorage(); await storage.write(key: my_key, value: my_value);
It seems to be so that only a few packages work in #pragma("vm:entry-point") functions, but this is one of them. I implemented it so that every time the app opens, it gets and handles the data from the secure storage before the app is launched.

Detecting flutter app opened from a terminated state with FCM and flutter_local_notifications

I am working on a flutter app that uses FCM data messages sent through cloud functions. In my app I'm receiving that data messages and then displaying a local notification. I need to be able to tap the local notification and have it direct the user to the correct screen. My current solution works when the app is in the foreground, or background, but NOT terminated. When it's terminated tapping on the notification appears to just open the app. Is there a way to detect if the app just opened from a terminated state? Below is my current code for when the notification is tapped, and the comments show what I want it to do
Future onSelectNotification(String payload) async {
Map data = json.decode(payload);
print('onSelectNotification: $data');
// if app is in foreground or background do this
if (data.containsKey('conversation_with')) {
print('Notification was for a conversation');
String conversationID = data['conversation_with'];
print('Conversation with UID: $conversationID');
PublicAppUser conversationWith =
await FriendDatabase().getPublicAppUser(conversationID);
navigatorKey.currentState!.pushNamed(
ConversationPublicUserScreen.routeName,
arguments: conversationWith);
}
// if it just opened from a terminated state do this
// ...
}

How to Tap on native iOS popup to allow Notifications. (Flutter Integration Test)

Flutter Driver code has to tap on the native "Allow" button to continue and simulate the correct user behaviour.
See this screenshot. Native iOS popup before app starts - Allow Notifications
App has not yet completely started and is waiting for this tap.
How does one get the driver to tap on the native iOS popup?
Any suggestions and ideas are welcome.
Here is the code for one attempt to wait for the app before continuing with other tests; it just awaits indefinitely:
setUpAll(() async {
driver = await FlutterDriver.connect();
await driver.waitUntilFirstFrameRasterized();
});
Here is another attempt at finding the word "Allow" in the popup and tapping on it:
test('Allow app to send Notifications.', () async {
final allow = find.byTooltip("Allow");
await delay(750);
await driver.tap(allow);
});
It does not find the word.
The issue is probably that Flutter Driver is not aware of the iOS native popup.
Other tests are very simple once in the app, for example, to tap on fields, enter text, scroll pages, etc.
Any ideas on how to do this?
Unfortunately this feature is currently not possible. Flutter Driver can't interact with native elements (v1.20.4).
https://github.com/flutter/flutter/issues/34345
https://github.com/flutter/flutter/issues/12561

Using uni_links when the app is in the background

My application has the following structure:
- InheritedWidget for dependencies
--> Splash Screen Page
--> Login Pages
--> Main Pages
When the app runs for the first time, I can use var link = await getInitialLink(); to get the value for the link that opened the app.
However, I cannot get the same result if I open the app on the background.
I tried to use
getLinksStream().listen((link) => (link) {
try {
var _latestUri;
if (link != null) _latestUri = Uri.parse(link);
print("=== Formated successfully a link!");
} on FormatException {
print("--- A link got here but was invalid");
}
});
For getting the link in the Splash Screen, but if the app is already open in the Login or Main pages, it won't go through the Splash Screen again.
Then, I tried to put it in the InheritedWidget, but alas, didn't get any result whatsoever.
So my question is: Where and how should I set up uni_links so that I can catch all incoming links even if the app is open?
Or better, is there an alternative for App Links/Universal Links that I can use?
Though it's not the best and most elegant way, I got around this.
First, I was not using getLinksStream correctly
Instead of
(link) => (link) {...}
It's
(link) {...}
Then, I need to put this subscription in my Splash Screen and do not dispose of it, so that it can listen to new events.
If anybody has a better solution, please free to add it
For this situation, you need to use both of getInitialUri() and getUriLinksStream(),
If app launchs directly u will get uri from getInitialUri, if app already running on background u will get uri from getUriLinksStream.