1. परिचय
पिछले अपडेट की तारीख: 19-10-2021
WebView Flutter प्लगिन की मदद से, अपने Android या iOS Flutter ऐप्लिकेशन में WebView विजेट जोड़ा जा सकता है. iOS पर WebView विजेट को WKWebView से सपोर्ट मिलता है. वहीं, Android पर WebView विजेट को WebView से सपोर्ट मिलता है. यह प्लगिन, वेब व्यू पर फ़्लटर विजेट रेंडर कर सकता है. उदाहरण के लिए, वेब व्यू के ऊपर ड्रॉप-डाउन मेन्यू रेंडर किया जा सकता है.
आपको क्या बनाना है
इस कोडलैब में, आपको Flutter SDK का इस्तेमाल करके, वेबव्यू की सुविधा वाला मोबाइल ऐप्लिकेशन बनाने का तरीका बताया जाएगा. आपका ऐप्लिकेशन:
WebView
में वेब कॉन्टेंट दिखानाWebView
के ऊपर स्टैक किए गए Flutter विजेट दिखाना- पेज लोड होने की प्रोग्रेस के इवेंट पर प्रतिक्रिया करना
WebViewController
की मदद सेWebView
को कंट्रोल करनाNavigationDelegate
का इस्तेमाल करके वेबसाइटों को ब्लॉक करना- JavaScript एक्सप्रेशन का आकलन करना
JavascriptChannels
की मदद से JavaScript से मिले कॉलबैक हैंडल करना- कुकी सेट करना, हटाना, जोड़ना या दिखाना
- ऐसेट, फ़ाइलों या एचटीएमएल वाले स्ट्रिंग से एचटीएमएल लोड और डिसप्ले करना
आपको क्या सीखने को मिलेगा
इस कोडलैब में, आपको webview_flutter
प्लगिन को अलग-अलग तरीकों से इस्तेमाल करने के बारे में जानकारी मिलेगी. जैसे:
webview_flutter
प्लगिन को कॉन्फ़िगर करने का तरीका- पेज लोड होने की प्रोग्रेस के इवेंट को मॉनिटर करने का तरीका
- पेज नेविगेशन को कंट्रोल करने का तरीका
WebView
को इतिहास में पीछे और आगे जाने का निर्देश देने का तरीका- JavaScript का आकलन कैसे करें. इसमें, दिखाए गए नतीजों का इस्तेमाल करना भी शामिल है
- JavaScript से Dart कोड को कॉल करने के लिए, कॉलबैक रजिस्टर करने का तरीका
- कुकी कैसे प्रबंधित करें
- ऐसेट, फ़ाइलों या एचटीएमएल वाले स्ट्रिंग से एचटीएमएल पेज लोड और दिखाने का तरीका
ज़रूरी शर्तें
- Android Studio 4.1 या इसके बाद का वर्शन (Android डेवलपमेंट के लिए)
- iOS डेवलपमेंट के लिए, Xcode 12 या इसके बाद का वर्शन
- Flutter SDK
- कोई कोड एडिटर, जैसे कि Android Studio या Visual Studio Code.
2. Flutter डेवलपमेंट एनवायरमेंट सेट अप करना
इस लैब को पूरा करने के लिए, आपको दो सॉफ़्टवेयर की ज़रूरत होगी — Flutter SDK और एडिटर.
इनमें से किसी भी डिवाइस पर कोडलैब चलाया जा सकता है:
- आपके पास Android या iOS डिवाइस होना चाहिए, जो आपके कंप्यूटर से कनेक्ट हो और डेवलपर मोड पर सेट हो.
- iOS सिम्युलेटर (इसके लिए, Xcode टूल इंस्टॉल करना ज़रूरी है).
- Android Emulator (इसे Android Studio में सेट अप करना ज़रूरी है).
3. शुरू करना
Flutter का इस्तेमाल शुरू करना
नया Flutter प्रोजेक्ट बनाने के कई तरीके हैं. Android Studio और Visual Studio Code, दोनों ही इस काम के लिए टूल उपलब्ध कराते हैं. प्रोजेक्ट बनाने के लिए, लिंक किए गए तरीकों का पालन करें या कमांड लाइन टर्मिनल में ये कमांड चलाएं.
$ flutter create --platforms=android,ios webview_in_flutter Creating project webview_in_flutter... Resolving dependencies in `webview_in_flutter`... Downloading packages... Got dependencies in `webview_in_flutter`. Wrote 74 files. All done! You can find general documentation for Flutter at: https://docs.flutter.dev/ Detailed API documentation is available at: https://api.flutter.dev/ If you prefer video documentation, consider: https://www.youtube.com/c/flutterdev In order to run your application, type: $ cd webview_in_flutter $ flutter run Your application code is in webview_in_flutter/lib/main.dart.
WebView Flutter प्लगिन को डिपेंडेंसी के तौर पर जोड़ना
Flutter ऐप्लिकेशन में कोई अतिरिक्त सुविधा जोड़ने के लिए, Pub पैकेज का इस्तेमाल करना सबसे सही तरीका है. इस कोडलैब में, आपको अपने प्रोजेक्ट में webview_flutter
प्लगिन जोड़ना होगा. टर्मिनल में ये कमांड चलाएं.
$ cd webview_in_flutter $ flutter pub add webview_flutter Resolving dependencies... Downloading packages... collection 1.18.0 (1.19.0 available) leak_tracker 10.0.5 (10.0.7 available) leak_tracker_flutter_testing 3.0.5 (3.0.7 available) material_color_utilities 0.11.1 (0.12.0 available) + plugin_platform_interface 2.1.8 string_scanner 1.2.0 (1.3.0 available) test_api 0.7.2 (0.7.3 available) + webview_flutter 4.9.0 + webview_flutter_android 3.16.7 + webview_flutter_platform_interface 2.10.0 + webview_flutter_wkwebview 3.15.0 Changed 5 dependencies! 6 packages have newer versions incompatible with dependency constraints. Try `flutter pub outdated` for more information.
अगर आपने pubspec.yaml की जांच की, तो अब आपको दिखेगा कि इसमें डिपेंडेंसी सेक्शन में webview_flutter
प्लगिन के लिए एक लाइन है.
Android minSDK को कॉन्फ़िगर करना
Android पर webview_flutter
प्लग इन का इस्तेमाल करने के लिए, आपको minSDK
को 20
पर सेट करना होगा. अपनी android/app/build.gradle
फ़ाइल में यहां बताए गए तरीके से बदलाव करें:
android/app/build.gradle
android {
//...
defaultConfig {
applicationId = "com.example.webview_in_flutter"
minSdk = 20 // Modify this line
targetSdk = flutter.targetSdkVersion
versionCode = flutterVersionCode.toInteger()
versionName = flutterVersionName
}
4. Flutter ऐप्लिकेशन में WebView विजेट जोड़ना
इस चरण में, आपको अपने आवेदन में WebView
जोड़ना होगा. वेबव्यू, पहले से मौजूद व्यू होते हैं. ऐप्लिकेशन डेवलपर के तौर पर आपके पास यह चुनने का विकल्प होता है कि आपको इन व्यू को अपने ऐप्लिकेशन में कैसे होस्ट करना है. Android पर, आपके पास वर्चुअल डिसप्ले और हाइब्रिड कंपोज़िशन में से कोई एक चुनने का विकल्प होता है. वर्चुअल डिसप्ले, Android के लिए डिफ़ॉल्ट रूप से उपलब्ध होता है. हालांकि, iOS हमेशा हाइब्रिड कंपोज़िशन का इस्तेमाल करता है.
वर्चुअल डिसप्ले और हाइब्रिड कंपोज़िशन के बीच के अंतर के बारे में ज़्यादा जानने के लिए, Platform Views की मदद से, अपने Flutter ऐप्लिकेशन में Android और iOS के नेटिव व्यू होस्ट करना लेख पढ़ें .
स्क्रीन पर वेबव्यू दिखाना
lib/main.dart
के कॉन्टेंट को इससे बदलें:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
),
body: WebViewWidget(
controller: controller,
),
);
}
}
इसे iOS या Android पर चलाने से, आपके डिवाइस पर WebView, फ़ुल ब्लीड ब्राउज़र विंडो के तौर पर दिखेगा. इसका मतलब है कि ब्राउज़र आपके डिवाइस पर फ़ुलस्क्रीन में दिखेगा. इसमें कोई बॉर्डर या मार्जिन नहीं होगा. स्क्रोल करने पर, आपको पेज के कुछ ऐसे हिस्से दिखेंगे जो शायद थोड़े अजीब लगें. ऐसा इसलिए है, क्योंकि JavaScript बंद है. flutter.dev को ठीक से रेंडर करने के लिए JavaScript की ज़रूरत होती है.
ऐप्लिकेशन चलाना
iOS या Android में Flutter ऐप्लिकेशन चलाकर Webview देखें. इसमें flutter.dev वेबसाइट दिखती है. इसके अलावा, ऐप्लिकेशन को Android एम्युलेटर या iOS सिम्युलेटर में चलाएं. शुरुआती वेबव्यू यूआरएल को अपनी वेबसाइट के यूआरएल से बदलें.
$ flutter run
मान लें कि आपके पास सही सिम्युलेटर या एम्युलेटर चल रहा है या कोई फ़िज़िकल डिवाइस अटैच है. ऐप्लिकेशन को अपने डिवाइस पर कंपाइल और डिप्लॉय करने के बाद, आपको कुछ ऐसा दिखना चाहिए:
5. पेज लोड इवेंट सुने जा रहे हैं
WebView
विजेट, पेज लोड होने की प्रोसेस से जुड़े कई इवेंट उपलब्ध कराता है. आपका ऐप्लिकेशन इन इवेंट को सुन सकता है. WebView
पेज लोड साइकल के दौरान, पेज लोड होने के तीन अलग-अलग इवेंट ट्रिगर होते हैं: onPageStarted
, onProgress
, और onPageFinished
. इस चरण में, पेज लोड होने का इंडिकेटर लागू किया जाएगा. बोनस के तौर पर, इससे यह पता चलेगा कि WebView
कॉन्टेंट एरिया पर Flutter कॉन्टेंट रेंडर किया जा सकता है.
अपने ऐप्लिकेशन में पेज लोड इवेंट जोड़ना
lib/src/web_view_stack.dart
पर एक नई सोर्स फ़ाइल बनाएं और उसमें यह कॉन्टेंट डालें:
lib/src/web_view_stack.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
const WebViewStack({super.key});
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..setNavigationDelegate(NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
))
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
इस कोड में, WebView
विजेट को Stack
में रैप किया गया है. साथ ही, पेज लोड होने का प्रतिशत 100% से कम होने पर, WebView
को LinearProgressIndicator
के साथ शर्त के आधार पर ओवरले किया गया है. इसमें प्रोग्राम की ऐसी स्थिति शामिल होती है जो समय के साथ बदलती रहती है. इसलिए, आपने इस स्थिति को StatefulWidget
से जुड़ी State
क्लास में सेव किया है.
इस नए WebViewStack
विजेट का इस्तेमाल करने के लिए, अपने lib/main.dart
में इस तरह बदलाव करें:
lib/main.dart
import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
),
body: const WebViewStack(),
);
}
}
ऐप्लिकेशन चलाने पर, आपको WebView
कॉन्टेंट एरिया के ऊपर पेज लोड होने का इंडिकेटर दिखेगा. यह इंडिकेटर, नेटवर्क की स्थिति और इस बात पर निर्भर करता है कि ब्राउज़र ने उस पेज को कैश मेमोरी में सेव किया है या नहीं जिस पर आपको नेविगेट करना है.
6. WebViewController के साथ काम करना
WebView विजेट से WebViewController को ऐक्सेस करना
WebView
विजेट, WebViewController
की मदद से प्रोग्राम के हिसाब से कंट्रोल करने की सुविधा देता है. इस कंट्रोलर को कॉलबैक के ज़रिए, WebView
विजेट बनाने के बाद उपलब्ध कराया जाता है. इस कंट्रोलर के उपलब्ध होने का तरीका एसिंक्रोनस है. इसलिए, यह Dart की एसिंक्रोनस Completer<T>
क्लास के लिए सबसे सही विकल्प है.
lib/src/web_view_stack.dart
को इस तरह अपडेट करें:
lib/src/web_view_stack.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
const WebViewStack({required this.controller, super.key}); // MODIFY
final WebViewController controller; // ADD
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
// REMOVE the controller that was here
@override
void initState() {
super.initState();
// Modify from here...
widget.controller.setNavigationDelegate(
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
),
);
// ...to here.
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller, // MODIFY
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
WebViewStack
विजेट अब आस-पास के विजेट में बनाए गए कंट्रोलर का इस्तेमाल करता है. इससे, WebViewWidget
के कंट्रोलर को ऐप्लिकेशन के अन्य हिस्सों के साथ शेयर किया जा सकेगा.
नेविगेशन कंट्रोल बनाना
WebView
का काम करना एक बात है, लेकिन पेज के इतिहास में आगे और पीछे जाने के साथ-साथ पेज को फिर से लोड करने की सुविधा भी काम की होगी. अच्छी बात यह है कि WebViewController
की मदद से, अपने ऐप्लिकेशन में यह सुविधा जोड़ी जा सकती है.
lib/src/navigation_controls.dart
पर एक नई सोर्स फ़ाइल बनाएं और उसमें यह जानकारी डालें:
lib/src/navigation_controls.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
const NavigationControls({required this.controller, super.key});
final WebViewController controller;
@override
Widget build(BuildContext context) {
return Row(
children: <Widget>[
IconButton(
icon: const Icon(Icons.arrow_back_ios),
onPressed: () async {
final messenger = ScaffoldMessenger.of(context);
if (await controller.canGoBack()) {
await controller.goBack();
} else {
messenger.showSnackBar(
const SnackBar(content: Text('No back history item')),
);
return;
}
},
),
IconButton(
icon: const Icon(Icons.arrow_forward_ios),
onPressed: () async {
final messenger = ScaffoldMessenger.of(context);
if (await controller.canGoForward()) {
await controller.goForward();
} else {
messenger.showSnackBar(
const SnackBar(content: Text('No forward history item')),
);
return;
}
},
),
IconButton(
icon: const Icon(Icons.replay),
onPressed: () {
controller.reload();
},
),
],
);
}
}
यह विजेट, कंस्ट्रक्शन के समय शेयर किए गए WebViewController
का इस्तेमाल करता है. इससे उपयोगकर्ता, IconButton
की मदद से WebView
को कंट्रोल कर पाता है.
AppBar में नेविगेशन कंट्रोल जोड़ना
अपडेट किए गए WebViewStack
और नए NavigationControls
के साथ, अब आपको इन सभी को अपडेट किए गए WebViewApp
में शामिल करना होगा. यहां हम शेयर किए गए WebViewController
को बनाते हैं. इस ऐप्लिकेशन में विजेट ट्री में सबसे ऊपर WebViewApp
मौजूद है. इसलिए, इसे इसी लेवल पर बनाना सही रहेगा.
lib/main.dart
फ़ाइल को इस तरह अपडेट करें:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart'; // ADD
import 'src/navigation_controls.dart'; // ADD
import 'src/web_view_stack.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
// Add from here...
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
// ...to here.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
// Add from here...
actions: [
NavigationControls(controller: controller),
],
// ...to here.
),
body: WebViewStack(controller: controller), // MODIFY
);
}
}
ऐप्लिकेशन चलाने पर, कंट्रोल वाला एक वेब पेज दिखना चाहिए:
7. NavigationDelegate की मदद से नेविगेशन को ट्रैक करना
WebView
आपके ऐप्लिकेशन को NavigationDelegate,
उपलब्ध कराता है. इससे आपका ऐप्लिकेशन, WebView
विजेट के पेज नेविगेशन को ट्रैक और कंट्रोल कर पाता है. जब WebView,
से नेविगेशन शुरू किया जाता है, तब NavigationDelegate
को कॉल किया जाता है. उदाहरण के लिए, जब कोई उपयोगकर्ता किसी लिंक पर क्लिक करता है. NavigationDelegate
कॉलबैक का इस्तेमाल करके यह कंट्रोल किया जा सकता है कि WebView
नेविगेशन जारी रखे या नहीं.
कस्टम NavigationDelegate रजिस्टर करना
इस चरण में, आपको YouTube.com पर नेविगेट करने से रोकने के लिए, NavigationDelegate
कॉलबैक रजिस्टर करना होगा. ध्यान दें कि इस आसान तरीके से लागू करने पर, YouTube का इनलाइन कॉन्टेंट भी ब्लॉक हो जाता है. यह कॉन्टेंट, Flutter API के दस्तावेज़ों के अलग-अलग पेजों पर दिखता है.
lib/src/web_view_stack.dart
को इस तरह अपडेट करें:
lib/src/web_view_stack.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
const WebViewStack({required this.controller, super.key});
final WebViewController controller;
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
@override
void initState() {
super.initState();
widget.controller.setNavigationDelegate(
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
// Add from here...
onNavigationRequest: (navigation) {
final host = Uri.parse(navigation.url).host;
if (host.contains('youtube.com')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Blocking navigation to $host',
),
),
);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
// ...to here.
),
);
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
अगले चरण में, आपको मेन्यू में एक आइटम जोड़ना होगा. इससे NavigationDelegate
क्लास का इस्तेमाल करके, NavigationDelegate
की टेस्टिंग की जा सकेगी.WebViewController
यह काम पढ़ने वाले व्यक्ति के लिए है कि वह कॉलबैक के लॉजिक को इस तरह से बढ़ाए कि वह सिर्फ़ YouTube.com पर पूरे पेज के नेविगेशन को ब्लॉक करे. साथ ही, एपीआई के दस्तावेज़ में YouTube के इनलाइन कॉन्टेंट को अब भी अनुमति दे.
8. ऐप्लिकेशन बार में मेन्यू बटन जोड़ना
अगले कुछ चरणों में, आपको AppBar
विजेट में एक मेन्यू बटन बनाना होगा. इसका इस्तेमाल JavaScript का आकलन करने, JavaScript चैनल चालू करने, और कुकी मैनेज करने के लिए किया जाता है. कुल मिलाकर, यह मेन्यू वाकई काम का है.
lib/src/menu.dart
पर एक नई सोर्स फ़ाइल बनाएं और उसमें यह जानकारी डालें:
lib/src/menu.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
enum _MenuOptions {
navigationDelegate,
}
class Menu extends StatelessWidget {
const Menu({required this.controller, super.key});
final WebViewController controller;
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await controller.loadRequest(Uri.parse('https://youtube.com'));
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
],
);
}
}
जब उपयोगकर्ता, YouTube पर जाएं मेन्यू विकल्प चुनता है, तब WebViewController
का loadRequest
तरीका लागू होता है. इस नेविगेशन को, पिछले चरण में बनाए गए navigationDelegate
कॉलबैक से ब्लॉक कर दिया जाएगा.
WebViewApp
की स्क्रीन पर मेन्यू जोड़ने के लिए, lib/main.dart
में इस तरह बदलाव करें:
lib/main.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'src/menu.dart'; // ADD
import 'src/navigation_controls.dart';
import 'src/web_view_stack.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const WebViewApp(),
),
);
}
class WebViewApp extends StatefulWidget {
const WebViewApp({super.key});
@override
State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
late final WebViewController controller;
@override
void initState() {
super.initState();
controller = WebViewController()
..loadRequest(
Uri.parse('https://flutter.dev'),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter WebView'),
actions: [
NavigationControls(controller: controller),
Menu(controller: controller), // ADD
],
),
body: WebViewStack(controller: controller),
);
}
}
अपना ऐप्लिकेशन चलाएं और YouTube पर जाएं मेन्यू आइटम पर टैप करें. आपको एक SnackBar दिखेगा. इसमें बताया जाएगा कि नेविगेशन कंट्रोलर ने YouTube पर नेविगेट करने की सुविधा को ब्लॉक कर दिया है.
9. JavaScript का आकलन करना
WebViewController
, मौजूदा पेज के कॉन्टेक्स्ट में JavaScript एक्सप्रेशन का आकलन कर सकता है. JavaScript का आकलन करने के दो अलग-अलग तरीके हैं: जिस JavaScript कोड से कोई वैल्यू नहीं मिलती उसके लिए runJavaScript
का इस्तेमाल करें. वहीं, जिस JavaScript कोड से कोई वैल्यू मिलती है उसके लिए runJavaScriptReturningResult
का इस्तेमाल करें.
JavaScript चालू करने के लिए, आपको WebViewController
को कॉन्फ़िगर करना होगा. इसके लिए, javaScriptMode
प्रॉपर्टी को JavascriptMode.unrestricted
पर सेट करना होगा. डिफ़ॉल्ट रूप से, javascriptMode
को JavascriptMode.disabled
पर सेट किया जाता है.
_WebViewStackState
क्लास को अपडेट करने के लिए, javascriptMode
सेटिंग को इस तरह जोड़ें:
lib/src/web_view_stack.dart
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
@override
void initState() {
super.initState();
widget.controller
..setNavigationDelegate( // Modify this line to use .. instead of .
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
onNavigationRequest: (navigation) {
final host = Uri.parse(navigation.url).host;
if (host.contains('youtube.com')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Blocking navigation to $host',
),
),
);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..setJavaScriptMode(JavaScriptMode.unrestricted); // Add this line
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
अब WebViewWidget
JavaScript को लागू कर सकता है. इसलिए, मेन्यू में runJavaScriptReturningResult
तरीके का इस्तेमाल करने का विकल्प जोड़ा जा सकता है.
अपने एडिटर या कीबोर्ड का इस्तेमाल करके, Menu क्लास को StatefulWidget में बदलें. lib/src/menu.dart
में बदलाव करके, इसे इस तरह बनाएं:
lib/src/menu.dart
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
enum _MenuOptions {
navigationDelegate,
userAgent, // Add this line
}
class Menu extends StatefulWidget { // Convert to StatefulWidget
const Menu({required this.controller, super.key});
final WebViewController controller;
@override // Add from here
State<Menu> createState() => _MenuState();
}
class _MenuState extends State<Menu> { // To here.
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate: // Modify from here
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
)); // To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
), // To here.
],
);
}
}
‘उपयोगकर्ता एजेंट दिखाएं' मेन्यू विकल्प पर टैप करने पर, JavaScript एक्सप्रेशन navigator.userAgent
को लागू करने का नतीजा, Snackbar
में दिखता है. ऐप्लिकेशन चलाने पर, आपको दिख सकता है कि Flutter.dev पेज अलग दिख रहा है. JavaScript चालू करके चलाने पर यह नतीजा मिला.
10. JavaScript चैनलों का इस्तेमाल करना
JavaScript चैनल की मदद से, आपका ऐप्लिकेशन WebViewWidget
के JavaScript कॉन्टेक्स्ट में कॉलबैक हैंडलर रजिस्टर कर सकता है. इन हैंडलर को, ऐप्लिकेशन के Dart कोड को वैल्यू वापस भेजने के लिए इस्तेमाल किया जा सकता है. इस चरण में, आपको एक SnackBar
चैनल रजिस्टर करना होगा. इसे XMLHttpRequest
के नतीजे के साथ कॉल किया जाएगा.
WebViewStack
क्लास को इस तरह अपडेट करें:
lib/src/web_view_stack.dart
class WebViewStack extends StatefulWidget {
const WebViewStack({required this.controller, super.key});
final WebViewController controller;
@override
State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
var loadingPercentage = 0;
@override
void initState() {
super.initState();
widget.controller
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (url) {
setState(() {
loadingPercentage = 0;
});
},
onProgress: (progress) {
setState(() {
loadingPercentage = progress;
});
},
onPageFinished: (url) {
setState(() {
loadingPercentage = 100;
});
},
onNavigationRequest: (navigation) {
final host = Uri.parse(navigation.url).host;
if (host.contains('youtube.com')) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Blocking navigation to $host',
),
),
);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
// Modify from here...
..setJavaScriptMode(JavaScriptMode.unrestricted)
..addJavaScriptChannel(
'SnackBar',
onMessageReceived: (message) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(message.message)));
},
);
// ...to here.
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
WebViewWidget(
controller: widget.controller,
),
if (loadingPercentage < 100)
LinearProgressIndicator(
value: loadingPercentage / 100.0,
),
],
);
}
}
Set
में मौजूद हर JavaScript चैनल के लिए, JavaScript कॉन्टेक्स्ट में एक चैनल ऑब्जेक्ट उपलब्ध कराया जाता है. इसे JavaScript चैनल name
के नाम से ही विंडो प्रॉपर्टी के तौर पर उपलब्ध कराया जाता है. JavaScript कॉन्टेक्स्ट से इसका इस्तेमाल करने के लिए, JavaScript चैनल पर postMessage
को कॉल करना होता है. इससे एक ऐसा मैसेज भेजा जाता है जिसे नाम वाले JavascriptChannel
के onMessageReceived
कॉलबैक हैंडलर को पास किया जाता है.
पहले जोड़े गए JavaScript चैनल का इस्तेमाल करने के लिए, एक और मेन्यू आइटम जोड़ें. यह आइटम, JavaScript कॉन्टेक्स्ट में XMLHttpRequest
को एक्ज़ीक्यूट करता है और SnackBar
JavaScript चैनल का इस्तेमाल करके नतीजे वापस भेजता है.
अब WebViewWidget
को हमारे JavaScript चैनलों के बारे में पता है,
. इसलिए, ऐप्लिकेशन को और बेहतर बनाने के लिए, एक उदाहरण जोड़ें. इसके लिए, Menu
क्लास में एक और PopupMenuItem
जोड़ें और अतिरिक्त फ़ंक्शनैलिटी जोड़ें.
_MenuOptions
को मेन्यू के अतिरिक्त विकल्प के साथ अपडेट करें. इसके लिए, javascriptChannel
की गिनती की वैल्यू जोड़ें. साथ ही, Menu
क्लास में इस तरह से लागू करें:
lib/src/menu.dart
enum _MenuOptions {
navigationDelegate,
userAgent,
javascriptChannel, // Add this option
}
class Menu extends StatefulWidget {
const Menu({required this.controller, super.key});
final WebViewController controller;
@override
State<Menu> createState() => _MenuState();
}
class _MenuState extends State<Menu> {
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
));
case _MenuOptions.javascriptChannel: // Add from here
await widget.controller.runJavaScript('''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
let response = JSON.parse(req.responseText);
SnackBar.postMessage("IP Address: " + response.ip);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();'''); // To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.javascriptChannel,
child: Text('Lookup IP Address'),
), // To here.
],
);
}
}
जब उपयोगकर्ता JavaScript चैनल का उदाहरण मेन्यू विकल्प चुनता है, तब इस JavaScript को लागू किया जाता है.
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
SnackBar.postMessage(req.responseText);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();
यह कोड, Public IP Address API को GET
अनुरोध भेजता है. इससे डिवाइस का आईपी पता मिलता है. इस नतीजे को SnackBar
में दिखाया गया है. इसके लिए, SnackBar
JavascriptChannel
पर postMessage
को चालू किया गया है.
11. कुकी मैनेज करना
आपका ऐप्लिकेशन, CookieManager
क्लास का इस्तेमाल करके WebView
में कुकी मैनेज कर सकता है. इस चरण में, आपको कुकी की सूची दिखानी है, कुकी की सूची मिटानी है, कुकी मिटानी है, और नई कुकी सेट करनी हैं. कुकी के इस्तेमाल के हर उदाहरण के लिए, _MenuOptions
में इस तरह से एंट्री जोड़ें:
lib/src/menu.dart
enum _MenuOptions {
navigationDelegate,
userAgent,
javascriptChannel,
// Add from here ...
listCookies,
clearCookies,
addCookie,
setCookie,
removeCookie,
// ... to here.
}
इस चरण में, बाकी बदलाव Menu
क्लास पर फ़ोकस करते हैं. इनमें Menu
क्लास को स्टेटलेस से स्टेटफ़ुल में बदलना भी शामिल है. यह बदलाव इसलिए ज़रूरी है, क्योंकि Menu
को CookieManager
का मालिकाना हक रखना चाहिए. साथ ही, बिना किसी स्थिति वाले विजेट में बदलाव किया जा सकता है. यह एक खराब कॉम्बिनेशन है.
नतीजे के तौर पर मिली State क्लास में CookieManager को इस तरह जोड़ें:
lib/src/menu.dart
class Menu extends StatefulWidget {
const Menu({required this.controller, super.key});
final WebViewController controller;
@override
State<Menu> createState() => _MenuState();
}
class _MenuState extends State<Menu> {
final cookieManager = WebViewCookieManager(); // Add this line
@override
Widget build(BuildContext context) {
// ...
_MenuState
क्लास में, Menu
क्लास में पहले से जोड़ा गया कोड और नया जोड़ा गया CookieManager
शामिल होगा. सेक्शन की अगली सीरीज़ में, _MenuState
में हेल्पर फ़ंक्शन जोड़े जाएंगे. ये फ़ंक्शन, मेन्यू में जोड़े जाने वाले आइटम को चालू करेंगे.
सभी कुकी की सूची पाना
आपको सभी कुकी की सूची पाने के लिए, JavaScript का इस्तेमाल करना होगा. इसके लिए, _MenuState
क्लास के आखिर में _onListCookies
नाम का एक हेल्पर मेथड जोड़ें. runJavaScriptReturningResult
तरीके का इस्तेमाल करके, आपका हेल्पर तरीका JavaScript कॉन्टेक्स्ट में document.cookie
को एक्ज़ीक्यूट करता है. इससे सभी कुकी की सूची मिलती है.
_MenuState
क्लास में यह जानकारी जोड़ें:
lib/src/menu.dart
Future<void> _onListCookies(WebViewController controller) async {
final String cookies = await controller
.runJavaScriptReturningResult('document.cookie') as String;
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(cookies.isNotEmpty ? cookies : 'There are no cookies.'),
),
);
}
सभी कुकी मिटाएं
WebView में मौजूद सभी कुकी मिटाने के लिए, CookieManager
क्लास के clearCookies
तरीके का इस्तेमाल करें. यह तरीका, एक Future<bool>
दिखाता है. अगर CookieManager
ने कुकी मिटा दी हैं, तो यह true
पर सेट हो जाता है. अगर मिटाने के लिए कोई कुकी नहीं थी, तो यह false
पर सेट हो जाता है.
_MenuState
क्लास में यह जानकारी जोड़ें:
lib/src/menu.dart
Future<void> _onClearCookies() async {
final hadCookies = await cookieManager.clearCookies();
String message = 'There were cookies. Now, they are gone!';
if (!hadCookies) {
message = 'There were no cookies to clear.';
}
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
),
);
}
कोई कुकी जोड़ना
JavaScript को लागू करके, कुकी जोड़ी जा सकती है. JavaScript दस्तावेज़ में कुकी जोड़ने के लिए इस्तेमाल किए जाने वाले एपीआई के बारे में MDN पर पूरी जानकारी दी गई है.
_MenuState
क्लास में यह जानकारी जोड़ें:
lib/src/menu.dart
Future<void> _onAddCookie(WebViewController controller) async {
await controller.runJavaScript('''var date = new Date();
date.setTime(date.getTime()+(30*24*60*60*1000));
document.cookie = "FirstName=John; expires=" + date.toGMTString();''');
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie added.'),
),
);
}
CookieManager की मदद से कुकी सेट करना
CookieManager का इस्तेमाल करके भी कुकी सेट की जा सकती हैं. इसके लिए, यह तरीका अपनाएं.
_MenuState
क्लास में यह जानकारी जोड़ें:
lib/src/menu.dart
Future<void> _onSetCookie(WebViewController controller) async {
await cookieManager.setCookie(
const WebViewCookie(name: 'foo', value: 'bar', domain: 'flutter.dev'),
);
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie is set.'),
),
);
}
किसी कुकी को हटाना
किसी कुकी को हटाने के लिए, एक नई कुकी जोड़ी जाती है. इस कुकी के लिए, समयसीमा खत्म होने की तारीख को पिछली तारीख के तौर पर सेट किया जाता है.
_MenuState
क्लास में यह जानकारी जोड़ें:
lib/src/menu.dart
Future<void> _onRemoveCookie(WebViewController controller) async {
await controller.runJavaScript(
'document.cookie="FirstName=John; expires=Thu, 01 Jan 1970 00:00:00 UTC" ');
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Custom cookie removed.'),
),
);
}
CookieManager मेन्यू आइटम जोड़ना
अब आपको सिर्फ़ मेन्यू के विकल्प जोड़ने हैं और उन्हें उन हेल्पर तरीकों से जोड़ना है जिन्हें आपने अभी जोड़ा है. _MenuState
क्लास को इस तरह अपडेट करें:
lib/src/menu.dart
class _MenuState extends State<Menu> {
final cookieManager = WebViewCookieManager();
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
));
case _MenuOptions.javascriptChannel:
await widget.controller.runJavaScript('''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
let response = JSON.parse(req.responseText);
SnackBar.postMessage("IP Address: " + response.ip);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();''');
case _MenuOptions.clearCookies: // Add from here
await _onClearCookies();
case _MenuOptions.listCookies:
await _onListCookies(widget.controller);
case _MenuOptions.addCookie:
await _onAddCookie(widget.controller);
case _MenuOptions.setCookie:
await _onSetCookie(widget.controller);
case _MenuOptions.removeCookie:
await _onRemoveCookie(widget.controller); // To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.javascriptChannel,
child: Text('Lookup IP Address'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.clearCookies,
child: Text('Clear cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.listCookies,
child: Text('List cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.addCookie,
child: Text('Add cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.setCookie,
child: Text('Set cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.removeCookie,
child: Text('Remove cookie'),
), // To here.
],
);
}
CookieManager का इस्तेमाल करना
ऐप्लिकेशन में जोड़ी गई सभी सुविधाओं का इस्तेमाल करने के लिए, यह तरीका आज़माएं:
- कुकी की सूची बनाएं को चुनें. इसमें, flutter.dev की ओर से सेट की गई Google Analytics कुकी की सूची होनी चाहिए.
- कुकी मिटाएं को चुनें. इसे यह रिपोर्ट करना चाहिए कि कुकी मिटा दी गई हैं.
- कुकी मिटाएं को फिर से चुनें. इसे यह रिपोर्ट करना चाहिए कि मिटाने के लिए कोई कुकी उपलब्ध नहीं थी.
- कुकी की सूची बनाएं को चुनें. इसमें यह जानकारी होनी चाहिए कि कोई कुकी मौजूद नहीं है.
- कुकी जोड़ें को चुनें. इसमें कुकी को जोड़े जाने की जानकारी दिखनी चाहिए.
- कुकी सेट करें को चुनें. इसे कुकी को सेट के तौर पर रिपोर्ट करना चाहिए.
- कुकी की सूची बनाएं को चुनें. इसके बाद, कुकी हटाएं को चुनें.
12. WebView में Flutter ऐसेट, फ़ाइलें, और एचटीएमएल स्ट्रिंग लोड करना
आपका ऐप्लिकेशन, अलग-अलग तरीकों का इस्तेमाल करके एचटीएमएल फ़ाइलें लोड कर सकता है और उन्हें WebView में दिखा सकता है. इस चरण में, pubspec.yaml
फ़ाइल में बताई गई फ़्लटर ऐसेट लोड की जाएगी. साथ ही, बताए गए पाथ पर मौजूद फ़ाइल लोड की जाएगी और एचटीएमएल स्ट्रिंग का इस्तेमाल करके पेज लोड किया जाएगा.
अगर आपको किसी तय किए गए पाथ पर मौजूद फ़ाइल लोड करनी है, तो आपको pubspec.yaml
में path_provider
जोड़ना होगा. यह फ़ाइल सिस्टम पर, आम तौर पर इस्तेमाल की जाने वाली जगहों का पता लगाने के लिए एक Flutter प्लगिन है.
कमांड लाइन में, यह कमांड चलाएं:
$ flutter pub add path_provider
ऐसेट को लोड करने के लिए, हमें pubspec.yaml
में ऐसेट का पाथ बताना होगा. pubspec.yaml
में ये लाइनें जोड़ें:
pubspec.yaml
# The following section is specific to Flutter packages.
flutter:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true
# Add from here
assets:
- assets/www/index.html
- assets/www/styles/style.css
# ... to here.
अपने प्रोजेक्ट में ऐसेट जोड़ने के लिए, यह तरीका अपनाएं:
- अपने प्रोजेक्ट के रूट फ़ोल्डर में,
assets
नाम की नई डायरेक्ट्री बनाएं. assets
फ़ोल्डर में,www
नाम की नई डायरेक्ट्री बनाएं.www
फ़ोल्डर में,styles
नाम की नई डायरेक्ट्री बनाएं.www
फ़ोल्डर में,index.html
नाम की नई फ़ाइल बनाएं.styles
फ़ोल्डर में,style.css
नाम की नई फ़ाइल बनाएं.
यहां दिए गए कोड को कॉपी करके, index.html
फ़ाइल में चिपकाएं:
assets/www/index.html
<!DOCTYPE html>
<!-- Copyright 2013 The Flutter Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<html lang="en">
<head>
<title>Load file or HTML string example</title>
<link rel="stylesheet" href="styles/style.css" />
</head>
<body>
<h1>Local demo page</h1>
<p>
This is an example page used to demonstrate how to load a local file or HTML
string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
webview</a> plugin.
</p>
</body>
</html>
style.css के लिए, एचटीएमएल हेडर स्टाइल सेट करने के लिए यहां दी गई कुछ लाइनों का इस्तेमाल करें:
assets/www/styles/style.css
h1 {
color: blue;
}
ऐसेट सेट हो गई हैं और इस्तेमाल के लिए तैयार हैं. इसलिए, अब उन तरीकों को लागू किया जा सकता है जिनकी ज़रूरत Flutter ऐसेट, फ़ाइलों या एचटीएमएल स्ट्रिंग को लोड करने और दिखाने के लिए होती है.
Flutter ऐसेट लोड करना
अभी बनाई गई ऐसेट को लोड करने के लिए, आपको WebViewController
का इस्तेमाल करके loadFlutterAsset
तरीके को कॉल करना होगा. साथ ही, ऐसेट का पाथ पैरामीटर के तौर पर देना होगा. अपने कोड के आखिर में यह तरीका जोड़ें:
lib/src/menu.dart
Future<void> _onLoadFlutterAssetExample(
WebViewController controller, BuildContext context) async {
await controller.loadFlutterAsset('assets/www/index.html');
}
डिवाइस पर मौजूद फ़ाइल लोड करना
अपने डिवाइस पर कोई फ़ाइल लोड करने के लिए, ऐसा तरीका जोड़ा जा सकता है जो loadFile
तरीके का इस्तेमाल करेगा. इसके लिए, आपको फिर से WebViewController
का इस्तेमाल करना होगा. यह String
लेता है, जिसमें फ़ाइल का पाथ होता है.
आपको सबसे पहले एचटीएमएल कोड वाली फ़ाइल बनानी होगी. इसके लिए, menu.dart
फ़ाइल में इंपोर्ट के ठीक नीचे, अपने कोड में सबसे ऊपर एचटीएमएल कोड को स्ट्रिंग के तौर पर जोड़ें.
lib/src/menu.dart
import 'dart:io'; // Add this line,
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart'; // And this one.
import 'package:webview_flutter/webview_flutter.dart';
// Add from here ...
const String kExamplePage = '''
<!DOCTYPE html>
<html lang="en">
<head>
<title>Load file or HTML string example</title>
</head>
<body>
<h1>Local demo page</h1>
<p>
This is an example page used to demonstrate how to load a local file or HTML
string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
webview</a> plugin.
</p>
</body>
</html>
''';
// ... to here.
File
बनाने और फ़ाइल में एचटीएमएल स्ट्रिंग लिखने के लिए, आपको दो तरीके जोड़ने होंगे. _onLoadLocalFileExample
, फ़ाइल को लोड करेगा. इसके लिए, वह पाथ को स्ट्रिंग के तौर पर उपलब्ध कराएगा. यह पाथ, _prepareLocalFile()
मेथड से मिलता है. अपने कोड में ये तरीके जोड़ें:
lib/src/menu.dart
Future<void> _onLoadLocalFileExample(
WebViewController controller, BuildContext context) async {
final String pathToIndex = await _prepareLocalFile();
await controller.loadFile(pathToIndex);
}
static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
final File indexFile = File('$tmpDir/www/index.html');
await Directory('$tmpDir/www').create(recursive: true);
await indexFile.writeAsString(kExamplePage);
return indexFile.path;
}
एचटीएमएल स्ट्रिंग लोड करें
एचटीएमएल स्ट्रिंग देकर किसी पेज को दिखाना बहुत आसान है. WebViewController
में एक ऐसा तरीका है जिसका इस्तेमाल किया जा सकता है. इसे loadHtmlString
कहा जाता है. इसमें एचटीएमएल स्ट्रिंग को आर्ग्युमेंट के तौर पर दिया जा सकता है. इसके बाद, WebView
में दिया गया एचटीएमएल पेज दिखेगा. अपने कोड में यह तरीका जोड़ें:
lib/src/menu.dart
Future<void> _onLoadFlutterAssetExample(
WebViewController controller, BuildContext context) async {
await controller.loadFlutterAsset('assets/www/index.html');
}
Future<void> _onLoadLocalFileExample(
WebViewController controller, BuildContext context) async {
final String pathToIndex = await _prepareLocalFile();
await controller.loadFile(pathToIndex);
}
static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
final File indexFile = File('$tmpDir/www/index.html');
await Directory('$tmpDir/www').create(recursive: true);
await indexFile.writeAsString(kExamplePage);
return indexFile.path;
}
// Add here ...
Future<void> _onLoadHtmlStringExample(
WebViewController controller, BuildContext context) async {
await controller.loadHtmlString(kExamplePage);
}
// ... to here.
मेन्यू आइटम जोड़ना
ऐसेट सेट हो गई हैं और इस्तेमाल के लिए तैयार हैं. साथ ही, सभी फ़ंक्शन के साथ तरीके बना लिए गए हैं. अब मेन्यू को अपडेट किया जा सकता है. _MenuOptions
enum में ये एंट्री जोड़ें:
lib/src/menu.dart
enum _MenuOptions {
navigationDelegate,
userAgent,
javascriptChannel,
listCookies,
clearCookies,
addCookie,
setCookie,
removeCookie,
// Add from here ...
loadFlutterAsset,
loadLocalFile,
loadHtmlString,
// ... to here.
}
अब जब enum अपडेट हो गया है, तो मेन्यू के विकल्प जोड़े जा सकते हैं. साथ ही, उन्हें अभी-अभी जोड़े गए हेल्पर तरीकों से जोड़ा जा सकता है. _MenuState
क्लास को इस तरह अपडेट करें:
lib/src/menu.dart
class _MenuState extends State<Menu> {
final cookieManager = WebViewCookieManager();
@override
Widget build(BuildContext context) {
return PopupMenuButton<_MenuOptions>(
onSelected: (value) async {
switch (value) {
case _MenuOptions.navigationDelegate:
await widget.controller
.loadRequest(Uri.parse('https://youtube.com'));
case _MenuOptions.userAgent:
final userAgent = await widget.controller
.runJavaScriptReturningResult('navigator.userAgent');
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('$userAgent'),
));
case _MenuOptions.javascriptChannel:
await widget.controller.runJavaScript('''
var req = new XMLHttpRequest();
req.open('GET', "https://api.ipify.org/?format=json");
req.onload = function() {
if (req.status == 200) {
let response = JSON.parse(req.responseText);
SnackBar.postMessage("IP Address: " + response.ip);
} else {
SnackBar.postMessage("Error: " + req.status);
}
}
req.send();''');
case _MenuOptions.clearCookies:
await _onClearCookies();
case _MenuOptions.listCookies:
await _onListCookies(widget.controller);
case _MenuOptions.addCookie:
await _onAddCookie(widget.controller);
case _MenuOptions.setCookie:
await _onSetCookie(widget.controller);
case _MenuOptions.removeCookie:
await _onRemoveCookie(widget.controller);
case _MenuOptions.loadFlutterAsset: // Add from here
if (!mounted) return;
await _onLoadFlutterAssetExample(widget.controller, context);
case _MenuOptions.loadLocalFile:
if (!mounted) return;
await _onLoadLocalFileExample(widget.controller, context);
case _MenuOptions.loadHtmlString:
if (!mounted) return;
await _onLoadHtmlStringExample(widget.controller, context);
// To here.
}
},
itemBuilder: (context) => [
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.navigationDelegate,
child: Text('Navigate to YouTube'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.userAgent,
child: Text('Show user-agent'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.javascriptChannel,
child: Text('Lookup IP Address'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.clearCookies,
child: Text('Clear cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.listCookies,
child: Text('List cookies'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.addCookie,
child: Text('Add cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.setCookie,
child: Text('Set cookie'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.removeCookie,
child: Text('Remove cookie'),
),
const PopupMenuItem<_MenuOptions>( // Add from here
value: _MenuOptions.loadFlutterAsset,
child: Text('Load Flutter Asset'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadHtmlString,
child: Text('Load HTML string'),
),
const PopupMenuItem<_MenuOptions>(
value: _MenuOptions.loadLocalFile,
child: Text('Load local file'),
), // To here.
],
);
}
ऐसेट, फ़ाइल, और एचटीएमएल स्ट्रिंग की जांच करना
अभी लागू किए गए कोड के काम करने की जांच करने के लिए, अपने डिवाइस पर कोड चलाएं और जोड़े गए नए मेन्यू आइटम में से किसी एक पर क्लिक करें. ध्यान दें कि _onLoadFlutterAssetExample
, style.css
का इस्तेमाल करके एचटीएमएल फ़ाइल के हेडर का रंग नीला कर देता है.
13. सब हो गया!
बधाई हो!!! आपने यह कोडलैब पूरा कर लिया है. इस कोडलैब का पूरा कोड, आपको कोडलैब रिपॉज़िटरी में मिल जाएगा.
ज़्यादा जानने के लिए, अन्य Flutter कोडलैब आज़माएं.