For creating Intent and Open Method Channel for read it.
first we need to change some in AndroidManifest.xml file. You can found it inside your flutter project in demo_project\android\app\src\main\AndroidManifest.xml
add extra lines in AndroidManifest.xml
AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.demo_project"><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /><uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /><queries><intent><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:mimeType="application/pdf" /></intent></queries><applicationandroid:label="demo_project"android:name="${applicationName}"android:icon="@mipmap/ic_launcher"><activityandroid:name=".MainActivity"android:exported="true"android:launchMode="singleTop"android:theme="@style/LaunchTheme"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:hardwareAccelerated="true"android:windowSoftInputMode="adjustResize"><!-- Specifies an Android theme to apply to this Activity as soon asthe Android process has started. This theme is visible to the userwhile the Flutter UI initializes. After that, this theme continuesto determine the Window background behind the Flutter UI. --><meta-dataandroid:name="io.flutter.embedding.android.NormalTheme"android:resource="@style/NormalTheme"/><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter><intent-filter><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.DEFAULT"/><data android:mimeType="application/pdf" /></intent-filter></activity><!-- Don't delete the meta-data below.This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --><meta-dataandroid:name="flutterEmbedding"android:value="2" /></application></manifest>
In Above code you see these extra lines you should add in your Android Manifest files. so Your android system can understand that which types of your app and which types of files your app handle. Such as my app is a pdf reader so i add this line you can used your line according to your app.
android:mimeType="application/pdf"
AndroidManifest.xml:
<intent-filter><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.DEFAULT"/><data android:mimeType="application/pdf" /></intent-filter>
Second
Second go to your MainActivity.kt file inside your project folder inside android folder
demo_project\android\app\src\main\kotlin\com\example\your_project_name\MainActivity.kt file.
Write this code inside MainActivity.kt
package com.example.demo_project
import android.content.Intent
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.embedding.android.FlutterActivity
class FileIntentHandler(private val activity: FlutterActivity) : MethodChannel.MethodCallHandler {
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method == "getFileIntentData") {
val intent : Intent? = activity.intent
val filePath: String? = intent?.data?.path
result.success(filePath)
} else {
result.notImplemented()
}
}
}
class MainActivity : FlutterActivity() {
private val channelName = "com.example.demo_project/openPDF" // Replace with your package name
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
// Initialize the platform channel and set the method call handler
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channelName)
.setMethodCallHandler(FileIntentHandler(this)::onMethodCall)
}
}
Remember : change package name to your actual package name.
Now you have to download some dependencies or i say some file for gradle.build file. which you don't worry. we do it in android stdio.
but first you have to remove all the dependency which is stored in pubsec.yaml file. you can do it by following command in vs code terminal or which ever terminal you used.
flutter clean
if you do not clean dependencies next step never complete. it show some error so you have to clean your dependencies.
when you cleaned all dependency you see error in dart file don't worry about that we can fixed it later.
For that you right click on android folder and choose Open in Android Stdio option
In the corner of android stdio you can see progress of download.
Now back into you VS code Editor and download your all dependency by one single click.
flutter pub get
It download all your dependencies according to your pubsec.yaml dependencies section have.
Now we are left only dart file. So we have distribute screen according to intent or some open our app directily. We can do this first we have to install flutter_plugin_android_lifecycle plugin to work in Method Channel. you can add this flutter pub add flutter_plugin_android_lifecycle.
Now we have free to work for Method channel. You do not need import this depedency in your dart file.
first import some basic things in flutter .dart file.
main.dart:
import 'package:flutter/material.dart';import 'package:flutter/services.dart';import 'dart:async';
_isIntent is false we prefer that user open our app directly. If intend occurs we will handle it in later. _pdfPath is used to stored our path.
main.dart:
const platform = MethodChannel('com.example.demo_project/openPDF');void main() async {WidgetsFlutterBinding.ensureInitialized();await _requestPermissionStatus();// Define the platform channel nameconst channelName = 'com.example.demo_project/openPDF';// Initialize the platform channelconst MethodChannel channel = MethodChannel(channelName);// Set up the handlerchannel.setMethodCallHandler((call) async {if (call.method == 'getFileIntentData') {// Handle the platform method call herefinal String? filePath = await getFileIntentData();if (filePath != null) {_pdfPath = filePath.toString();_isIntent = true;}print('Received PDF file path: $filePath');}});runApp(MyApp());}
'com.example.demo_project/openPDF' change it to your channel name in MainActivity.kt.
WidgetsFlutterBinding.ensureInitialized();
this line is necessary. don't forget it.
MainActivity.kt:private val channelName = "com.example.demo_project/openPDF" // Replace with your package name
MainActivity.kt:
private val channelName = "com.example.demo_project/openPDF" // Replace with your package name
and also change it with your call method 'getFileIntentData'
in MainActivity.kt
MainActivity.kt: if (call.method == "getFileIntentData") {
MainActivity.kt:
if (call.method == "getFileIntentData") {
Remember : Your channelName and call.method both are same in
main.dart and MainActivity.dart.
Now we create getFileIntentData( ) function which return path of our file.
main.dart:Future<String?> getFileIntentData() async { try { final String? filePath = await platform.invokeMethod('getFileIntentData'); return filePath; } on PlatformException catch (e) { print('Error: $e'); return null; }}
main.dart:
Future<String?> getFileIntentData() async {try {final String? filePath = await platform.invokeMethod('getFileIntentData');return filePath;} on PlatformException catch (e) {print('Error: $e');return null;}}
Above code channel.setMethodCallHandler it Checks whether intent call or not. If intent called this function works. It means it handle Intent.
For used intent in our code we used Future Widget so that we can differentiate route to homeScreen or other Screen.
main.dart:class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return FutureBuilder<String?>( future: getFileIntentData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // Return a loading indicator or splash screen while waiting for intent data. return const MaterialApp( home: CircularProgressIndicator(), // Replace with your loading UI. ); } else if (snapshot.hasError) { // Handle error case. return MaterialApp( home: Text('Error: ${snapshot.error}'), // Replace with your error UI. ); } else if (snapshot.hasData) { // If intent data is available, navigate to PDFScreen. return MaterialApp( home: PDFScreen( path: snapshot.data! .replaceAll("external_files", "storage/emulated/0")), ); } else { // Default case: show HomeScreen. return const MaterialApp( home: HomeScreen(), ); } }, ); }}
main.dart:
class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return FutureBuilder<String?>(future: getFileIntentData(),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {// Return a loading indicator or splash screen while waiting for intent data.return const MaterialApp(home: CircularProgressIndicator(), // Replace with your loading UI.);} else if (snapshot.hasError) {// Handle error case.return MaterialApp(home:Text('Error: ${snapshot.error}'), // Replace with your error UI.);} else if (snapshot.hasData) {// If intent data is available, navigate to PDFScreen.return MaterialApp(home: PDFScreen(path: snapshot.data!.replaceAll("external_files", "storage/emulated/0")),);} else {// Default case: show HomeScreen.return const MaterialApp(home: HomeScreen(),);}},);}}
Remember : This code path such as external_files so we replace it by this "storage/emulated/ 0". It works fine.
In the End
I upload my all code which contain permission and other things. Just check it.
main.dart:import 'package:flutter/material.dart';import 'package:permission_handler/permission_handler.dart';import 'dart:io';import 'dart:async';import 'package:demo_project/pdf_reader.dart';
import 'package:flutter/services.dart';import 'package:demo_project/screen/pdf_open.dart';
BuildContext? appContext;bool _isIntent = false;String? _pdfPath;
const platform = MethodChannel('com.example.demo_project/openPDF');
void main() async { WidgetsFlutterBinding.ensureInitialized(); await _requestPermissionStatus();
// Define the platform channel name const channelName = 'com.example.demo_project/openPDF';
// Initialize the platform channel const MethodChannel channel = MethodChannel(channelName);
// Set up the handler channel.setMethodCallHandler((call) async { if (call.method == 'getFileIntentData') { // Handle the platform method call here final String? filePath = await getFileIntentData(); if (filePath != null) { _pdfPath = filePath.toString(); _isIntent = true; } print('Received PDF file path: $filePath'); } });
runApp(MyApp());}
Future<String?> getFileIntentData() async { try { final String? filePath = await platform.invokeMethod('getFileIntentData'); return filePath; } on PlatformException catch (e) { print('Error: $e'); return null; }}
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return FutureBuilder<String?>( future: getFileIntentData(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { // Return a loading indicator or splash screen while waiting for intent data. return const MaterialApp( home: CircularProgressIndicator(), // Replace with your loading UI. ); } else if (snapshot.hasError) { // Handle error case. return MaterialApp( home: Text('Error: ${snapshot.error}'), // Replace with your error UI. ); } else if (snapshot.hasData) { // If intent data is available, navigate to PDFScreen. return MaterialApp( home: PDFScreen( path: snapshot.data! .replaceAll("external_files", "storage/emulated/0")), ); } else { // Default case: show HomeScreen. return const MaterialApp( home: HomeScreen(), ); } }, ); }}
Future<bool> _requestPermissionStatus() async { // final status = await Permission.storage.request(); // if (!status.isGranted) { // await Permission.storage.request(); // } PermissionStatus status = await Permission.manageExternalStorage.request(); // if (status.isGranted) { // print("Granted Permission"); // } return status == PermissionStatus.granted;}
main.dart:
import 'package:flutter/material.dart';import 'package:permission_handler/permission_handler.dart';import 'dart:io';import 'dart:async';import 'package:demo_project/pdf_reader.dart';import 'package:flutter/services.dart';import 'package:demo_project/screen/pdf_open.dart';BuildContext? appContext;bool _isIntent = false;String? _pdfPath;const platform = MethodChannel('com.example.demo_project/openPDF');void main() async {WidgetsFlutterBinding.ensureInitialized();await _requestPermissionStatus();// Define the platform channel nameconst channelName = 'com.example.demo_project/openPDF';// Initialize the platform channelconst MethodChannel channel = MethodChannel(channelName);// Set up the handlerchannel.setMethodCallHandler((call) async {if (call.method == 'getFileIntentData') {// Handle the platform method call herefinal String? filePath = await getFileIntentData();if (filePath != null) {_pdfPath = filePath.toString();_isIntent = true;}print('Received PDF file path: $filePath');}});runApp(MyApp());}Future<String?> getFileIntentData() async {try {final String? filePath = await platform.invokeMethod('getFileIntentData');return filePath;} on PlatformException catch (e) {print('Error: $e');return null;}}class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return FutureBuilder<String?>(future: getFileIntentData(),builder: (context, snapshot) {if (snapshot.connectionState == ConnectionState.waiting) {// Return a loading indicator or splash screen while waiting for intent data.return const MaterialApp(home: CircularProgressIndicator(), // Replace with your loading UI.);} else if (snapshot.hasError) {// Handle error case.return MaterialApp(home:Text('Error: ${snapshot.error}'), // Replace with your error UI.);} else if (snapshot.hasData) {// If intent data is available, navigate to PDFScreen.return MaterialApp(home: PDFScreen(path: snapshot.data!.replaceAll("external_files", "storage/emulated/0")),);} else {// Default case: show HomeScreen.return const MaterialApp(home: HomeScreen(),);}},);}}Future<bool> _requestPermissionStatus() async {// final status = await Permission.storage.request();// if (!status.isGranted) {// await Permission.storage.request();// }PermissionStatus status = await Permission.manageExternalStorage.request();// if (status.isGranted) {// print("Granted Permission");// }return status == PermissionStatus.granted;}
Comments
Post a Comment