deep linking test

This commit is contained in:
mohamadmahdi jebeli 2025-07-14 10:59:17 +03:30
parent 047de45e3b
commit 86913a973b
4 changed files with 62 additions and 80 deletions

View File

@ -106,7 +106,7 @@
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="web.didvan.com" /> <data android:scheme="https" android:host="test.didvan.com" />
</intent-filter> </intent-filter>
</activity> </activity>

View File

@ -3,8 +3,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:android_intent_plus/android_intent.dart';
import 'package:app_links/app_links.dart';
import 'package:bot_toast/bot_toast.dart'; import 'package:bot_toast/bot_toast.dart';
import 'package:didvan/config/theme_data.dart'; import 'package:didvan/config/theme_data.dart';
import 'package:didvan/firebase_options.dart'; import 'package:didvan/firebase_options.dart';
@ -35,18 +33,19 @@ import 'package:provider/provider.dart';
import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:sentry_flutter/sentry_flutter.dart'; import 'package:sentry_flutter/sentry_flutter.dart';
// پکیج جدید برای Deep Linking
import 'package:app_links/app_links.dart';
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
// متغیر استاتیک برای نگهداری لینک اولیه
Uri? initialURI;
@pragma('vm:entry-point') @pragma('vm:entry-point')
Future<void> _backgroundCallbackHomeWidget(Uri? uri) async { Future<void> _backgroundCallbackHomeWidget(Uri? uri) async {
await HomeWidget.saveWidgetData("uri", uri!.host); if (uri != null) {
AndroidIntent intent = const AndroidIntent( await HomeWidget.saveWidgetData("uri", uri.host);
action: 'android.intent.action.RUN', }
package: 'com.didvan.didvanapp',
componentName: 'com.didvan.didvanapp.MainActivity',
);
await intent.launch();
return;
} }
void main() async { void main() async {
@ -59,10 +58,8 @@ void main() async {
try { try {
if (Platform.isAndroid) { if (Platform.isAndroid) {
await FlutterDownloader.initialize( await FlutterDownloader.initialize(
debug: debug: true,
true, ignoreSsl: true
ignoreSsl:
true
); );
} }
} catch (e) { } catch (e) {
@ -74,7 +71,7 @@ void main() async {
options: DefaultFirebaseOptions.currentPlatform); options: DefaultFirebaseOptions.currentPlatform);
await FirebaseApi().initNotification(); await FirebaseApi().initNotification();
} catch (e) { } catch (e) {
debugPrint; debugPrint(e.toString());
} }
await SentryFlutter.init( await SentryFlutter.init(
@ -98,38 +95,33 @@ class Didvan extends StatefulWidget {
class _DidvanState extends State<Didvan> with WidgetsBindingObserver { class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
late AppLinks _appLinks; late AppLinks _appLinks;
StreamSubscription<Uri>? _linkSubscription; StreamSubscription<Uri>? _linkSubscription;
@override
void didChangeDependencies() {
super.didChangeDependencies();
}
@override @override
void initState() { void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState(); super.initState();
WidgetsBinding.instance.addObserver(this);
// مقداردهی اولیه و گوش دادن به لینکها در اینجا انجام میشود
_initDeepLinks(); _initDeepLinks();
} }
@override @override
void dispose() { void dispose() {
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
_linkSubscription?.cancel(); _linkSubscription?.cancel(); // لغو کردن subscription
if (MediaService.currentPodcast != null) { if (MediaService.currentPodcast != null) {
MediaService.audioPlayer.dispose(); MediaService.audioPlayer.dispose();
} }
super.dispose(); super.dispose();
} }
/// منطق جدید برای مدیریت لینکها با app_links
Future<void> _initDeepLinks() async { Future<void> _initDeepLinks() async {
_appLinks = AppLinks(); _appLinks = AppLinks();
// بررسی لینک اولیه در زمان باز شدن اپلیکیشن // لینک اولیه را فقط در متغیر ذخیره میکنیم
final initialUri = await _appLinks.getInitialLink(); initialURI = await _appLinks.getInitialLink();
if (initialUri != null) {
_navigateTo(initialUri);
}
// گوش دادن به لینکهای جدید زمانی که اپلیکیشن در حال اجراست // به لینکهای جدید زمانی که اپلیکیشن باز است گوش میدهیم
_linkSubscription = _appLinks.uriLinkStream.listen((uri) { _linkSubscription = _appLinks.uriLinkStream.listen((uri) {
_navigateTo(uri); _navigateTo(uri);
}); });
@ -146,9 +138,6 @@ class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
} }
} }
bool b = true;
@override @override
void didChangeAppLifecycleState(AppLifecycleState state) async { void didChangeAppLifecycleState(AppLifecycleState state) async {
if (!kIsWeb) { if (!kIsWeb) {
@ -171,33 +160,15 @@ class _DidvanState extends State<Didvan> with WidgetsBindingObserver {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiProvider( return MultiProvider(
providers: [ providers: [
ChangeNotifierProvider<PodcastsState>( ChangeNotifierProvider<PodcastsState>(create: (context) => PodcastsState()),
create: (context) => PodcastsState(), ChangeNotifierProvider<MediaProvider>(create: (context) => MediaProvider()),
), ChangeNotifierProvider<UserProvider>(create: (context) => UserProvider()),
ChangeNotifierProvider<MediaProvider>( ChangeNotifierProvider<ThemeProvider>(create: (context) => ThemeProvider()),
create: (context) => MediaProvider(), ChangeNotifierProvider<StudioDetailsState>(create: (context) => StudioDetailsState()),
), ChangeNotifierProvider<HistoryAiChatState>(create: (context) => HistoryAiChatState()),
ChangeNotifierProvider<UserProvider>( ChangeNotifierProvider<AiState>(create: (context) => AiState()),
create: (context) => UserProvider(), ChangeNotifierProvider<AiChatState>(create: (context) => AiChatState()),
), ChangeNotifierProvider<BotAssistantsState>(create: (context) => BotAssistantsState()),
ChangeNotifierProvider<ThemeProvider>(
create: (context) => ThemeProvider(),
),
ChangeNotifierProvider<StudioDetailsState>(
create: (context) => StudioDetailsState(),
),
ChangeNotifierProvider<HistoryAiChatState>(
create: (context) => HistoryAiChatState(),
),
ChangeNotifierProvider<AiState>(
create: (context) => AiState(),
),
ChangeNotifierProvider<AiChatState>(
create: (context) => AiChatState(),
),
ChangeNotifierProvider<BotAssistantsState>(
create: (context) => BotAssistantsState(),
),
], ],
child: Consumer<ThemeProvider>( child: Consumer<ThemeProvider>(
builder: (context, themeProvider, child) => Container( builder: (context, themeProvider, child) => Container(

View File

@ -1,5 +1,3 @@
// ignore_for_file: deprecated_member_use
import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/design_config.dart';
import 'package:didvan/constants/assets.dart'; import 'package:didvan/constants/assets.dart';
import 'package:didvan/main.dart'; import 'package:didvan/main.dart';
@ -89,9 +87,6 @@ class _SplashState extends State<Splash> {
Future<void> _initialize(ThemeProvider themeProvider, Future<void> _initialize(ThemeProvider themeProvider,
UserProvider userProvider, MediaProvider mediaProvider) async { UserProvider userProvider, MediaProvider mediaProvider) async {
try { try {
// if (!kIsWeb) {
// await AppInitializer.onCheckUpdate(context);
// }
if (kIsWeb) { if (kIsWeb) {
html.window.onBeforeUnload.listen((event) { html.window.onBeforeUnload.listen((event) {
StorageService.webStorage StorageService.webStorage
@ -136,21 +131,24 @@ class _SplashState extends State<Splash> {
await ServerDataProvider.getData(); await ServerDataProvider.getData();
} }
navigatorKey.currentState!.pushReplacementNamed( // --- بخش اصلاح شده ---
token == null ? Routes.authenticaion : Routes.home, // ابتدا بررسی میکنیم که کاربر باید به کدام صفحه اصلی برود
arguments: token == null ? false : null, final String destinationRoute = token == null ? Routes.authenticaion : Routes.home;
final dynamic routeArguments = token == null ? false : {'showDialogs': true};
// اگر لینک ورودی وجود داشت، آن را به عنوان آرگومان به صفحه Home میفرستیم
if (destinationRoute == Routes.home && initialURI != null) {
(routeArguments as Map)['deepLinkUri'] = initialURI;
initialURI = null; // لینک را مصرف میکنیم تا دوباره استفاده نشود
}
// در نهایت به مسیر تعیین شده میرویم
await navigatorKey.currentState!.pushReplacementNamed(
destinationRoute,
arguments: routeArguments,
); );
// --- پایان بخش اصلاح شده ---
return;
// await HomeWidget.getWidgetData<String>("cRouteGoTo", defaultValue: '')
// .then((cRouteGoTo) async {
// if (cRouteGoTo!.isNotEmpty) {
// navigatorKey.currentState!
// .pushNamed(cRouteGoTo.toString(), arguments:cRouteArgs );
// HomeWidget.saveWidgetData("cRouteGoTo", '');
// }
// });
} catch (e) { } catch (e) {
setState(() { setState(() {
_errorOccured = true; _errorOccured = true;

View File

@ -0,0 +1,13 @@
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.didvan.didvanapp",
"sha256_cert_fingerprints": [
"02:5A:86:49:AE:B4:FF:FE:5B:D0:C6:D7:F9:FF:85:60:F0:CF:AE:2F:39:8C:9D:F6:0D:4A:41:5D:EA:07:BE:8B",
"CA:F0:F8:9D:6D:5C:70:A1:C0:E8:F6:4D:19:DA:49:12:D4:F9:D6:C1:DB:E7:1C:B5:4B:ED:F5:A5:AA:DA:EE:DB"
]
}
}
]