commit 2b75d2b088aae9c0b9028e078f42ba30033632b9 Author: ayub Date: Sun Aug 10 13:41:02 2025 +0700 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d71f6ea --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +.dart_tool/ + +.packages +.pub/ + +build/ +.idea/ diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..30de70f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.acceptSuggestionOnEnter": "on" +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..2b6f053 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,79 @@ +# CHANGELOG + +## 2.0.2 + +* File not sharing issue fixed addresses issues -> #17, #16 + +## 2.0.1 + +* Is installed Fix for android 11 and above + +## 2.0.0 + +* Upgraded to NULL safety + +## 1.1.1 + +* Read me examples updated + +## 1.1.0 + +* Plugin respects Business whatsapp +* **Breaking Change** + * fileShare function takes list of paths instead of single path. + * Multiple images, files can be shared + +## 1.0.9 + +* Home page modified + +## 1.0.8 + +* ```isInstalled()``` method for checking whatsapp installed in device or not + +## 1.0.7 + +* Documented and optimized for whatsapp share + +## 1.0.6 + +* Whatsapp share + +## 1.0.5 +* Fix sdk environment + +## 1.0.4 +* Update to android v2 embedding + +## 1.0.3 + +* Fix share image top view controller dismissal bug on iOS 13+ +* Update to use the new platforms definition + +## 1.0.2+1 + +* Fix Android bug (FileUriExposedException) on new versions with FileProvider implementation (see the readme to configure) + +## 1.0.1+1 + +* Remove unused codes and improve description + +## 1.0.1 + +* Fix: Get the top most ViewController(IOS embedded support) + +## 1.0.0 + +* **BREAKING CHANGE**: Add support to AndroidX +* **BREAKING CHANGE**: Separate in two methods share (to share messages and links) and shareFile (to share files) +* Add ChooserTitle (Just for Android) +* Add Text +* Add Docs + +## 0.0.5 + +* Move documents_picker plugin to example project + +## 0.0.1 + +* Add file share. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1bcdbc1 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Amit Patil + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..a4e7456 --- /dev/null +++ b/README.md @@ -0,0 +1,121 @@ +# [Whatsapp Share Plugin](https://pub.dev/packages/whatsapp_share) + +[![pub package](https://img.shields.io/pub/v/whatsapp_share.svg)](https://pub.dartlang.org/packages/flutter_share) + + +A Flutter plugin for Android providing a simple way to share a message, link or local files to specific WhatsApp contact. + +## Features: + +* Share messages or link urls to specific contact. +* Share local files to specific contact. + + +## Installation + +First, add this to your package's pubspec.yaml file: +``` +dependencies: + whatsapp_share: ^1.1.1 +``` + +Now in your Dart code, you can use: +``` +import 'package:whatsapp_share/whatsapp_share.dart'; +``` +## Installation (Platform Specific) + +### iOS + +Add if not exists one row to the `ios/podfile` after target runner: + +``` +... + +target 'Runner' do + use_frameworks! + +... +``` + +### Android + +If you pretends to use the file share, you need to configure the file provider, this will give access to the files turning possible to share with other applications. + +Add to `AndroidManifest.xml`: + +``` + +... + + + + +``` +Obs: You can change the android:name if you have an extension of file provider. + +Add `res/xml/provider_paths.xml`: + +``` + + + + +``` + +If you want to learn more about file provider you can access: + + - https://developer.android.com/reference/android/support/v4/content/FileProvider + +## How to use? + +Here is an snippets app displaying the two whatsapp share methods . + +### Whatsapp installed in this device ? + +```Dart + Future isInstalled() async { + final val = await WhatsappShare.isInstalled( + package: Package.businessWhatsapp + ); + print('Whatsapp Business is installed: $val'); + } +``` +If whatsapp is not installed, please do not call ```WhatsappShare.share()``` and ```WhatsappShare.shareFile()``` + + + +### Share text, links + +```Dart + + Future share() async { + await WhatsappShare.share( + text: 'Whatsapp share text', + linkUrl: 'https://flutter.dev/', + phone: '911234567890', + ); + } + +``` + +### Share images, files + +```_image1.path``` contains path of the file which is shared to the whatsapp. + +```Dart + + Future shareFile() async { + await WhatsappShare.shareFile( + phone: '911234567890', + filePath: [_image1.path, _image2.path], + ); + } + +``` \ No newline at end of file diff --git a/android/.classpath b/android/.classpath new file mode 100644 index 0000000..8d8d85f --- /dev/null +++ b/android/.classpath @@ -0,0 +1,6 @@ + + + + + + diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..c6cbe56 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,8 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/android/.project b/android/.project new file mode 100644 index 0000000..fc23720 --- /dev/null +++ b/android/.project @@ -0,0 +1,23 @@ + + + whatsapp_share + Project whatsapp_share created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000..e889521 --- /dev/null +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..e1e2f74 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,41 @@ +group 'com.example.whatsapp_share' +version '1.0-SNAPSHOT' + +buildscript { + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.3.0' + } +} + +rootProject.allprojects { + repositories { + google() + jcenter() + } +} + +apply plugin: 'com.android.library' + +android { + namspace 'com.example.whatsapp_share' + compileSdkVersion 33 + + defaultConfig { + minSdkVersion 16 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + lintOptions { + disable 'InvalidPackage' + } +} + +dependencies { + api 'commons-io:commons-io:2.6' + implementation 'androidx.core:core:1.3.2' +} + diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..755300e --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M + +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..613c380 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'whatsapp_share' diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..a941cf3 --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/android/src/main/java/com/example/whatsapp_share/WhatsappShare.java b/android/src/main/java/com/example/whatsapp_share/WhatsappShare.java new file mode 100644 index 0000000..a43dec4 --- /dev/null +++ b/android/src/main/java/com/example/whatsapp_share/WhatsappShare.java @@ -0,0 +1,226 @@ +package com.example.whatsapp_share; + +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.text.TextUtils; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; + +import java.io.File; +import java.util.ArrayList; + +import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugin.common.MethodCall; +import io.flutter.plugin.common.MethodChannel; +import io.flutter.plugin.common.MethodChannel.MethodCallHandler; +import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry.Registrar; + + +/** WhatsappShare */ +public class WhatsappShare implements FlutterPlugin, MethodCallHandler { + private Context context; + private MethodChannel methodChannel; + + public WhatsappShare() {} + + /** Plugin registration. */ + @SuppressWarnings("deprecation") + public static void registerWith(io.flutter.plugin.common.PluginRegistry.Registrar registrar) { + final WhatsappShare instance = new WhatsappShare(); + instance.onAttachedToEngine(registrar.context(), registrar.messenger()); + } + + @Override + public void onAttachedToEngine(FlutterPluginBinding binding) { + onAttachedToEngine(binding.getApplicationContext(), binding.getBinaryMessenger()); + } + + private void onAttachedToEngine(Context applicationContext, BinaryMessenger messenger) { + this.context = applicationContext; + methodChannel = new MethodChannel(messenger, "whatsapp_share"); + methodChannel.setMethodCallHandler(this); + } + + @Override + public void onDetachedFromEngine(FlutterPluginBinding binding) { + context = null; + methodChannel.setMethodCallHandler(null); + methodChannel = null; + } + + @Override + public void onMethodCall(MethodCall call, Result result) { + if (call.method.equals("shareFile")) { + shareFile(call, result); + } else if (call.method.equals("share")) { + share(call, result); + } else if (call.method.equals("isInstalled")) { + isInstalled(call, result); + } else { + result.notImplemented(); + } + } + + private boolean isPackageInstalled(String packageName, PackageManager packageManager) { + try + { + packageManager.getPackageInfo(packageName, 0); + return true; + } + catch (PackageManager.NameNotFoundException e) { + return false; + } + } + + private void isInstalled(MethodCall call, Result result) { + try + { + String packageName = call.argument("package"); + + if (packageName == null || packageName.isEmpty()) + { + Log.println(Log.ERROR, "", "FlutterShare Error: Package name null or empty"); + result.error("FlutterShare:Package name cannot be null or empty", null, null); + return; + } + + PackageManager pm = context.getPackageManager(); + boolean isInstalled = isPackageInstalled(packageName, pm); + result.success(isInstalled); + } + catch (Exception ex) + { + Log.println(Log.ERROR, "", "FlutterShare: Error"); + result.error(ex.getMessage(), null, null); + } + } + + private void share(MethodCall call, Result result) { + try + { + String title = call.argument("title"); + String text = call.argument("text"); + String linkUrl = call.argument("linkUrl"); + String chooserTitle = call.argument("chooserTitle"); + String phone = call.argument("phone"); + String packageName = call.argument("package"); + + if (title == null || title.isEmpty()) + { + Log.println(Log.ERROR, "", "FlutterShare Error: Title null or empty"); + result.error("FlutterShare: Title cannot be null or empty", null, null); + return; + } else if(phone == null || phone.isEmpty()) + { Log.println(Log.ERROR, "", "FlutterShare Error: phone null or empty"); + result.error("FlutterShare: phone cannot be null or empty", null, null); + return; + } else if (packageName == null || packageName.isEmpty()) + { + Log.println(Log.ERROR, "", "FlutterShare Error: Package name null or empty"); + result.error("FlutterShare:Package name cannot be null or empty", null, null); + return; + } + + ArrayList extraTextList = new ArrayList<>(); + + if (text != null && !text.isEmpty()) { + extraTextList.add(text); + } + if (linkUrl != null && !linkUrl.isEmpty()) { + extraTextList.add(linkUrl); + } + + String extraText = ""; + + if (!extraTextList.isEmpty()) { + extraText = TextUtils.join("\n\n", extraTextList); + } + + Intent intent = new Intent(); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setAction(Intent.ACTION_SEND); + intent.setType("text/plain"); + intent.setPackage(packageName); + intent.putExtra("jid",phone + "@s.whatsapp.net"); + intent.putExtra(Intent.EXTRA_SUBJECT, title); + intent.putExtra(Intent.EXTRA_TEXT, extraText); + + //Intent chooserIntent = Intent.createChooser(intent, chooserTitle); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + + result.success(true); + } + catch (Exception ex) + { + Log.println(Log.ERROR, "", "FlutterShare: Error"); + result.error(ex.getMessage(), null, null); + } + } + + private void shareFile(MethodCall call, Result result) { + ArrayList filePaths = new ArrayList(); + ArrayList files = new ArrayList(); + try + { + String title = call.argument("title"); + String text = call.argument("text"); + filePaths = call.argument("filePath"); + String chooserTitle = call.argument("chooserTitle"); + String phone = call.argument("phone"); + String packageName = call.argument("package"); + + if (filePaths == null || filePaths.isEmpty()) + { + Log.println(Log.ERROR, "", "FlutterShare: ShareLocalFile Error: filePath null or empty"); + result.error("FlutterShare: FilePath cannot be null or empty", null, null); + return; + } else if(phone == null || phone.isEmpty()) + { Log.println(Log.ERROR, "", "FlutterShare Error: phone null or empty"); + result.error("FlutterShare: phone cannot be null or empty", null, null); + return; + } else if (packageName == null || packageName.isEmpty()) + { + Log.println(Log.ERROR, "", "FlutterShare Error: Package name null or empty"); + result.error("FlutterShare:Package name cannot be null or empty", null, null); + return; + } + + for(int i=0;i + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.example" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration. + minSdkVersion flutter.minSdkVersion + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..45d523a --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..ac71bb8 --- /dev/null +++ b/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + diff --git a/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt new file mode 100644 index 0000000..e793a00 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/example/example/MainActivity.kt @@ -0,0 +1,6 @@ +package com.example.example + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/example/android/app/src/main/res/drawable-v21/launch_background.xml b/example/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/example/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/example/android/app/src/main/res/values-night/styles.xml b/example/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/example/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/example/android/app/src/main/res/xml/file_paths.xml b/example/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..6b889fe --- /dev/null +++ b/example/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..45d523a --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle new file mode 100644 index 0000000..69456e1 --- /dev/null +++ b/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.9.10' + repositories { + google() + mavenCentral() + } + + dependencies { + classpath 'com.android.tools.build:gradle:7.1.2' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/example/android/gradle.properties b/example/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/example/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..cb24abd --- /dev/null +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/example/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/example/lib/main.dart b/example/lib/main.dart new file mode 100644 index 0000000..64f3487 --- /dev/null +++ b/example/lib/main.dart @@ -0,0 +1,123 @@ +import 'dart:async'; +import 'dart:developer'; +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:whatsapp_share/whatsapp_share.dart'; +import 'package:image_picker/image_picker.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:screenshot/screenshot.dart'; + +void main() => runApp(MyApp()); + +// ignore: must_be_immutable +class MyApp extends StatelessWidget { + final _controller = ScreenshotController(); + File? _image; + + MyApp({super.key}); + + Future share() async { + await WhatsappShare.share( + text: 'Example share text', + linkUrl: 'https://flutter.dev/', + phone: '911234567890', + ); + } + + Future shareFile() async { + await getImage(); + Directory? directory; + if (Platform.isAndroid) { + directory = await getExternalStorageDirectory(); + } else { + directory = await getApplicationDocumentsDirectory(); + } + debugPrint('${directory?.path} / ${_image?.path}'); + + await WhatsappShare.shareFile( + phone: '911234567890', + filePath: ["${_image?.path}"], + ); + } + + Future isInstalled() async { + final val = await WhatsappShare.isInstalled(package: Package.whatsapp); + debugPrint('Whatsapp is installed: $val'); + } + + Future shareScreenShot() async { + Directory? directory; + if (Platform.isAndroid) { + directory = await getExternalStorageDirectory(); + } else { + directory = await getApplicationDocumentsDirectory(); + } + + final String? localPath = + await _controller.captureAndSave(directory!.path); + + await Future.delayed(const Duration(seconds: 1)); + if (localPath == null) { + log("localPath is null"); + } + + await WhatsappShare.shareFile( + phone: '911234567890', + filePath: [localPath!], + ); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + home: Scaffold( + appBar: AppBar( + title: const Text('Whatsapp Share'), + ), + body: Center( + child: Screenshot( + controller: _controller, + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ElevatedButton( + onPressed: share, + child: const Text('Share text and link'), + ), + ElevatedButton( + onPressed: shareFile, + child: const Text('Share Image'), + ), + ElevatedButton( + onPressed: shareScreenShot, + child: const Text('Share screenshot'), + ), + ElevatedButton( + onPressed: isInstalled, + child: const Text('is Installed'), + ), + ], + ), + ), + ), + ), + ); + } + + ///Pick Image From gallery using image_picker plugin + Future getImage() async { + try { + XFile? pickedFile = + // ignore: deprecated_member_use + await ImagePicker().pickImage(source: ImageSource.gallery); + + if (pickedFile != null) { + _image = File(pickedFile.path); + } else {} + } catch (er) { + log(er.toString()); + } + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock new file mode 100644 index 0000000..0d0e2b8 --- /dev/null +++ b/example/pubspec.lock @@ -0,0 +1,457 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" + source: hosted + version: "1.17.2" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: fd832b5384d0d6da4f6df60b854d33accaaeb63aa9e10e736a87381f08dee2cb + url: "https://pub.dev" + source: hosted + version: "0.3.3+5" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" + source: hosted + version: "1.0.6" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + file_picker: + dependency: "direct main" + description: + name: file_picker + sha256: be325344c1f3070354a1d84a231a1ba75ea85d413774ec4bdf444c023342e030 + url: "https://pub.dev" + source: hosted + version: "5.5.0" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492" + url: "https://pub.dev" + source: hosted + version: "0.9.2+1" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "182c3f8350cee659f7b115e956047ee3dc672a96665883a545e81581b9a82c72" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: "0aa47a725c346825a2bd396343ce63ac00bda6eff2fbc43eabe99737dede8262" + url: "https://pub.dev" + source: hosted + version: "2.6.1" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0 + url: "https://pub.dev" + source: hosted + version: "0.9.3+1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04 + url: "https://pub.dev" + source: hosted + version: "2.0.3" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: f185ac890306b5779ecbd611f52502d8d4d63d27703ef73161ca0407e815f02c + url: "https://pub.dev" + source: hosted + version: "2.0.16" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: transitive + description: + name: http + sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: b6951e25b795d053a6ba03af5f710069c99349de9341af95155d52665cb4607c + url: "https://pub.dev" + source: hosted + version: "0.8.9" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: d32a997bcc4ee135aebca8e272b7c517927aa65a74b9c60a81a2764ef1a0462d + url: "https://pub.dev" + source: hosted + version: "0.8.7+5" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "869fe8a64771b7afbc99fc433a5f7be2fea4d1cb3d7c11a48b6b579eb9c797f0" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: c5538cacefacac733c724be7484377923b476216ad1ead35a0d2eadcdc0fc497 + url: "https://pub.dev" + source: hosted + version: "0.8.8+2" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: ed9b00e63977c93b0d2d2b343685bed9c324534ba5abafbb3dfbd6a780b1b514 + url: "https://pub.dev" + source: hosted + version: "2.9.1" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb" + url: "https://pub.dev" + source: hosted + version: "0.2.1+1" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + lints: + dependency: transitive + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + path_provider: + dependency: "direct main" + description: + name: path_provider + sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "6b8b19bd80da4f11ce91b2d1fb931f3006911477cec227cce23d3253d80df3f1" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + platform: + dependency: transitive + description: + name: platform + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d + url: "https://pub.dev" + source: hosted + version: "2.1.6" + screenshot: + dependency: "direct main" + description: + name: screenshot + sha256: "455284ff1f5b911d94a43c25e1385485cf6b4f288293eba68f15dad711c7b81c" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" + whatsapp_share: + dependency: "direct main" + description: + path: ".." + relative: true + source: path + version: "2.0.1" + win32: + dependency: transitive + description: + name: win32 + sha256: "9e82a402b7f3d518fb9c02d0e9ae45952df31b9bf34d77baf19da2de03fc2aaa" + url: "https://pub.dev" + source: hosted + version: "5.0.7" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + url: "https://pub.dev" + source: hosted + version: "1.0.3" +sdks: + dart: ">=3.1.0-185.0.dev <4.0.0" + flutter: ">=3.10.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml new file mode 100644 index 0000000..82107b2 --- /dev/null +++ b/example/pubspec.yaml @@ -0,0 +1,98 @@ +name: example +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: '>=2.18.6 <3.0.0' + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + screenshot: ^2.1.0 + path_provider: ^2.1.1 + image_picker: ^0.8.6+1 + file_picker: ^5.2.5 + + whatsapp_share: + path: ../ + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.5 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^2.0.1 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# 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 + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/flutter_share.iml b/flutter_share.iml new file mode 100644 index 0000000..73e7ebd --- /dev/null +++ b/flutter_share.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/flutter_share_android.iml b/flutter_share_android.iml new file mode 100644 index 0000000..ac5d744 --- /dev/null +++ b/flutter_share_android.iml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/whatsapp_share.dart b/lib/whatsapp_share.dart new file mode 100644 index 0000000..e8faff1 --- /dev/null +++ b/lib/whatsapp_share.dart @@ -0,0 +1,94 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +/// Select Whatsapp Type +enum Package { whatsapp, businessWhatsapp } + +class WhatsappShare { + static const MethodChannel _channel = MethodChannel('whatsapp_share'); + + /// Checks whether whatsapp is installed in device or not + /// + /// [Package] is optional enum parameter which is defualt to [Package.whatsapp] + /// for business whatsapp set it to [Package.businessWhatsapp], it cannot be null + /// + /// return true if installed otherwise false. + static Future isInstalled({Package package = Package.whatsapp}) async { + String _package; + _package = package.index == 0 ? "com.whatsapp" : "com.whatsapp.w4b"; + final bool? success = + await _channel.invokeMethod('isInstalled', { + "package": _package, + }); + return success; + } + + /// Shares a message or/and link url with whatsapp. + /// - Text: Is the [text] of the message. + /// - LinkUrl: Is the [linkUrl] to include with the message. + /// - Phone: is the [phone] contact number to share with. + + static Future share({ + required String phone, + String? text, + String? linkUrl, + Package package = Package.whatsapp, + }) async { + assert(phone.isNotEmpty); + + String _package; + _package = package.index == 0 ? "com.whatsapp" : "com.whatsapp.w4b"; + + final bool? success = + await _channel.invokeMethod('share', { + 'title': ' ', + 'text': text, + 'linkUrl': linkUrl, + 'chooserTitle': ' ', + 'phone': phone, + 'package': _package, + }); + + return success; + } + + /// Shares a local file with whatsapp. + /// - Text: Is the [text] of the message. + /// - FilePath: Is the List of paths which can be prefilled. + /// - Phone: is the [phone] contact number to share with. + static Future shareFile({ + required List filePath, + required String phone, + @Deprecated( + "No support for text along with files, this field is ignored") + String? text, + Package package = Package.whatsapp, + }) async { + assert(filePath.isNotEmpty); + assert(phone.isNotEmpty); + + if (filePath.isEmpty) { + throw FlutterError('FilePath cannot be Empty'); + } else if (phone.isEmpty) { + throw FlutterError('Phone cannot be Empty'); + } + + String _package; + _package = package.index == 0 ? "com.whatsapp" : "com.whatsapp.w4b"; + + final bool? success = + await _channel.invokeMethod('shareFile', { + 'title': ' ', + 'text': ' ', + 'filePath': filePath, + 'chooserTitle': ' ', + 'phone': phone, + 'package': _package, + }); + + return success; + } +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..850d1d1 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,165 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + collection: + dependency: transitive + description: + name: collection + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + url: "https://pub.dev" + source: hosted + version: "1.17.2" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + url: "https://pub.dev" + source: hosted + version: "0.12.16" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + meta: + dependency: transitive + description: + name: meta + sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path: + dependency: transitive + description: + name: path + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" + source: hosted + version: "1.8.3" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + url: "https://pub.dev" + source: hosted + version: "0.6.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" +sdks: + dart: ">=3.1.0-185.0.dev <4.0.0" + flutter: ">=1.20.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..ded9e88 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,26 @@ +name: whatsapp_share +description: Simple way to share message, links or files from your flutter app to specific contact in whatsapp +version: 2.0.2 +homepage: https://github.com/amitpatil215/whatsapp_share + + + +dependencies: + flutter: + sdk: flutter + +flutter: + plugin: + platforms: + android: + package: com.example.whatsapp_share + pluginClass: WhatsappShare + +dev_dependencies: + flutter_test: + sdk: flutter + + +environment: + sdk: '>=2.12.0 <4.0.0' + flutter: ">=1.20.0" \ No newline at end of file