我正在使用firebase_dynamic_links:^ 0.5.0在我的flutter应用程序中实现设置密码功能。由管理员创建用户时,用户会收到一封电子邮件。这封电子邮件中有一个动态链接。单击后,用户将被重定向到
1.应用商店/游戏商店(如果他/她没有应用)。
2.如果已安装应用程序,则在应用程序中打开设置密码屏幕。
firebase_dynamic_links提供了两种方法:
1.getInitialLink将来会检索打开应用程序的链接。
2.onLink回调,用于监听在应用程序处于 Activity 状态或后台时打开的链接。
当应用程序处于终止状态并按下链接时,一切都会顺利进行,但是当应用程序处于后台时,导航将无法正常工作。
void main() => runApp(MaterialApp(
theme: new ThemeData(
primaryColor: Colours.appThemeColour,
),
onGenerateRoute: (RouteSettings settings) {
switch (settings.name) {
case '/': return new MyCustomRoute(
builder: (_) => new SplashScreen(),
settings: settings,
);
case '/setpassword': return new MyCustomRoute(
builder: (_) => new SetPassword(settings.arguments),
settings: settings,
);
...
}
}
)
);
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
Uri deepLink;
_handleDeepLink(Uri deepLink) async{
if (deepLink != null) {
print("querParam=${deepLink.queryParameters["token"]}");
if(deepLink.queryParameters["otp"].toString()=="1"){
if(deepLink.queryParameters["token"]!=null){
String _status =await _networkUtil.verifyUser(deepLink.queryParameters["token"].toString());
Navigator.of(context).pushReplacementNamed('/setpassword',arguments: _status );
}else{
Navigator.of(context).pushReplacementNamed('/setpassword',arguments: "unknownError" );
}
}
else{
if(deepLink.queryParameters["token"]!=null){
String _status =await _networkUtil.verifyUser(deepLink.queryParameters["token"].toString());
SchedulerBinding.instance.addPostFrameCallback((_) {
Navigator.of(context).pushReplacementNamed('/resetpassword');
});
}else{
Navigator.of(context).pushReplacementNamed('/resetpassword');
}
}
}
}
}
initDynamicLinks() async {
final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink();
final Uri deepLink = data?.link;
if (deepLink != null) {
_handleDeepLink(deepLink);
}
FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLink) async {
final Uri deepLink = dynamicLink?.link;
_handleDeepLink(deepLink);
},
onError: (OnLinkErrorException e) async {
print('onLinkError');
print(e.message);
}
);
}
@override
initState(){
initDynamicLinks().then((){
...
});
}
当应用程序是背景并且单击链接时,它应该导航到设置密码屏幕,但是(通过我在下面提到的一个异常(exception))进入到将应用程序移至背景时打开的屏幕。
D / ViewRootImpl @ 5c26021MainActivity:MSG_WINDOW_FOCUS_CHANGED 0
D / SurfaceView(25703):返回中继:oldFrame = [0,0] [1440,2560] newFrame = [0,0] [1440,2560] result = 0x5 surface = {Surface(name = null)/ @ 0x54b5e07 isValid = false 0}
D / ViewRootImpl @ 5c26021MainActivity:mHardwareRenderer.destroy()#1
D / ViewRootImpl @ 5c26021MainActivity:中继返回:oldFrame = [0,0] [1440,2560] newFrame = [0,0] [1440,2560] result = 0x5 surface = {isValid = false 0} surfaceGenerationChanged = true
D / InputTransport(25703):输入通道损坏:fd = 92
D / ViewRootImpl @ 5c26021MainActivity:mHardwareRenderer.destroy()#1
D / ViewRootImpl @ 5c26021MainActivity:中继返回:oldFrame = [0,0] [1440,2560] newFrame = [0,0] [1440,2560] result = 0x1 surface = {isValid = false 0} surfaceGenerationChanged = false
D / ViewRootImpl @ 5c26021MainActivity:mHardwareRenderer.destroy()#1
D / ViewRootImpl @ 5c26021MainActivity:中继返回:oldFrame = [0,0] [1440,2560] newFrame = [0,0] [1440,2560] result = 0x1 surface = {isValid = false 0} surfaceGenerationChanged = false
D / SurfaceView(25703):返回中继:oldFrame = [0,0] [1440,2560] newFrame = [0,0] [1440,2560] result = 0x7 surface = {Surface(name = null)/ @ 0x54b5e07 isValid = true 543154356736}
D / mali_winsys(25703):EGLint new_window_surface(egl_winsys_display *,void *,EGLSurface,EGLConfig,egl_winsys_surface **,egl_color_buffer_format *,EGLBoolean)返回0x3000,[1440x2560] -format:1
I / flutter(25703):querParam = e144efdbd666e615a47ebe18e25a556d
D / ViewRootImpl @ 5c26021MainActivity:中继返回:oldFrame = [0,0] [1440,2560] newFrame = [0,0] [1440,2560] result = 0x7 surface = {isValid = true 542519654912} surfaceGenerationChanged = true
D / ViewRootImpl @ 5c26021MainActivity:mHardwareRenderer.initialize()mSurface = {isValid = true 542519654912} hwInitialized = true
D / mali_winsys(25703):EGLint new_window_surface(egl_winsys_display *,void *,EGLSurface,EGLConfig,egl_winsys_surface **,egl_color_buffer_format *,EGLBoolean)返回0x3000,[1440x2560] -format:1
D / ViewRootImpl @ 5c26021MainActivity:MSG_WINDOW_FOCUS_CHANGED 1
D / ViewRootImpl @ 5c26021MainActivity:mHardwareRenderer.initializeIfNeeded()#2 mSurface = {isValid = true 542519654912}
V / InputMethodManager(25703):起始输入:tba=android.view.inputmethod.EditorInfo@6fb193a nm:com.root.amployee ic = null
I / InputMethodManager(25703):[IMM] startInputInner-mService.startInputOrWindowGainedFocus
D / InputTransport(25703):构建的输入通道:fd = 93
E / flutter(25703):[错误:flutter / lib / ui / ui_dart_state.cc(148)]未处理的异常:NoSuchMethodError:方法'ancestorStateOfType'被调用为null。
E / flutter(25703):接收者:null
E / flutter(25703):尝试调用:ancestorStateOfType(“TypeMatcher”的实例)
E / flutter(25703):#0 Object.noSuchMethod(dart:core-patch / object_patch.dart:50:5)
最佳答案
这是库本身的问题。因为您当前无法访问您访问的context
。所以我建议您在MaterialApp
或CupertinoApp
中创建全局导航器状态
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final _navigatorKey = GlobalKey<NavigatorState>();
@override
Widget build(BuildContext context) {
return MaterialApp(
key: _navigatorKey,
home: Container(),
);
}
}