# Flutter Navigator 進階應用 - 深層鏈接&網頁URL
在前一篇[Navigator介紹](https://hackmd.io/lxmLX9h6TCCnOFMBfAwaGg?view)用路由器小部件在頁面之間移動,以聲明的方式導航你的APP。
那當我們希望**可以透過網址來到達指定頁面**,例如:為一個促銷活動生成一個特殊的二維碼,然後讓用戶掃描二維碼訪問你的應用程序中的特定產品,而Navigator 2.0也提供了這類功能。
## Deep Link 深層鏈接
深層鏈接是一個URL,可以導航到你的APP中的一個特定目的地。你可以把深度鏈接想像成你在網絡瀏覽器中輸入的URL地址,**可以直接進入網站的特定頁面而不是主頁。**
## 調整設定檔
### IOS
ios/Runner/Info.plist
```xml
<key>FlutterDeepLinkingEnabled</key>
<true/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>yenyen.com</string>
<key>CFBundleURLSchemes</key>
<array>
<string>fooderlich</string>
</array>
</dict>
</array>
```

### Android
```xml
<!-- Deep linking -->
<meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
<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="fooderlich"
android:host="yenyen.com" />
</intent-filter>
```

> 注意事項:
android:scheme="fooderlich"
android:host="yenyen.com"
輸入adb指令時記得要跟設定檔相符,後續內容也會有相關Demo
## 程式範例
### 主程式
main.dart
```dart
class _FooderlichState extends State<Fooderlich> {
//略...
final _appStateManager = AppStateManager(); //提供的路由設定管理pages的內容
final routeParser = AppRouteParser(); //將路由資訊解析成自定義的路由設定類別
late AppRouter _appRouter;
@override
void initState() {
super.initState();
//給予初始值
_appRouter = AppRouter(
appStateManager: _appStateManager,
//略
);
}
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => _appStateManager,
),
],
child: return MaterialApp.router(
theme: theme,
title: 'Fooderlich',
routeInformationParser: routeParser,
routerDelegate: _appRouter,
);
);
}
}
```
#### 參考資料
https://ithelp.ithome.com.tw/m/articles/10263763
### routeInformationParser
將路由資訊解析成自定義的路由設定類別,
#### navigation/app_route.dart
```dart
import 'app_link.dart';
class AppRouteParser extends RouteInformationParser<AppLink> {
@override
Future<AppLink> parseRouteInformation(
RouteInformation routeInformation) async {
final link = AppLink.fromLocation(routeInformation.location);
return link;
}
@override
RouteInformation restoreRouteInformation(AppLink appLink) {
return RouteInformation(location: appLink.toLocation());
}
}
```
#### navigation/app_link.dart
將收到的data進行解析
```dart
class AppLink {
static const String homePath = '/home';
static const String onboardingPath = '/onboarding';
static const String loginPath = '/login';
static const String profilePath = '/profile';
static const String itemPath = '/item';
static const String tabParam = 'tab';
static const String idParam = 'id';
String? location;
int? currentTab;
String? itemId;
AppLink({
this.location,
this.currentTab,
this.itemId,
});
static AppLink fromLocation(String? location) {
location = Uri.decodeFull(location ?? '');
final uri = Uri.parse(location);
final params = uri.queryParameters;
final currentTab = int.tryParse(params[AppLink.tabParam] ?? '');
final itemId = params[AppLink.idParam];
final link = AppLink(
location: uri.path,
currentTab: currentTab,
itemId: itemId,
);
return link;
}
String toLocation() {
String addKeyValPair({
required String key,
String? value,
}) =>
value == null ? '' : '$key=$value&';
switch (location) {
case loginPath:
return loginPath;
case onboardingPath:
return onboardingPath;
case profilePath:
return profilePath;
case itemPath:
String loc = '$itemPath?';
loc += addKeyValPair(
key: idParam,
value: itemId,
);
return Uri.encodeFull(loc);
default:
var loc = '$homePath?';
loc += addKeyValPair(
key: tabParam,
value: currentTab.toString(),
);
return Uri.encodeFull(loc);
}
}
}
```
## adb測試
### 跳轉到指定頁面
開啟控制台輸入
```command
adb shell am start -a android.intent.action.VIEW \
-c android.intent.category.BROWSABLE \
-d 'fooderlich://yenyen.com/home?tab=1'
```
* -s: 對特定機器下adb指令
* shell am start: 開啟或執行shell指令activity
* -a: actiot
* -c: category
* -d: data
### 除錯
[Flutter - 疑難炸症](https://hackmd.io/@BzWzq-x9Rb2G4WG03gcyKg/HkQ-sePtc#adb%E7%9B%B8%E9%97%9C)
###### tags: `flutter`