Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
### 3.0.2
[Android] Fix false "no email Managers available" when sending without attachments on Android 11+ by removing
PackageManager pre-query for ACTION_SENDTO and launching intent directly
[Example] Migrate Android build to Flutter's declarative Gradle plugin (dev.flutter.flutter-plugin-loader /
dev.flutter.flutter-gradle-plugin), update to Android compileSdk 36, and migrate embedding to v2.

### 3.0.1
[root] add analysis options
[test] remove usage of deprecated `setMockMethodCallHandler` in tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.ActivityNotFoundException;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;

import android.net.Uri;
import android.os.Build;
Expand Down Expand Up @@ -70,7 +70,12 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
mResult = result;
try {
final Intent intent = mail(call);
activity.startActivityForResult(intent, MAIL_ACTIVITY_REQUEST_CODE);
try {
activity.startActivityForResult(intent, MAIL_ACTIVITY_REQUEST_CODE);
} catch (ActivityNotFoundException e) {
result.error("not_available", "no email Managers available", null);
mResult = null;
}
Comment on lines +75 to +78

Copilot AI Sep 2, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The variable mResult is being set to null in the catch block, but it's also set to null in the existing catch block for FlutterMailerException below. Consider extracting this cleanup into a helper method to avoid duplication.

Copilot uses AI. Check for mistakes.
} catch (FlutterMailerException e) {
result.error(e.errorCode, e.errorMessage, e.errorDetails);
mResult = null;
Expand Down Expand Up @@ -164,20 +169,13 @@ private Intent mail(MethodCall options) throws FlutterMailerException {
}
}

PackageManager manager = context.getPackageManager();
List<ResolveInfo> list = manager.queryIntentActivities(intent, 0);

if (list == null || list.size() == 0) {
Log.e(TAG, "size is null or Zero");
throw new FlutterMailerException("not_available", "no email Managers available", null);
}

if (list.size() == 1) {
return intent;
} else if (options.hasArgument(APP_SCHEMA) && options.argument(APP_SCHEMA) != null && isAppInstalled((String) options.argument(APP_SCHEMA))) {
// If a specific package schema is requested, set it directly and let the system
// resolve it; avoid pre-querying PackageManager to keep compatibility with
// Android 11+ package visibility restrictions.
if (options.hasArgument(APP_SCHEMA) && options.argument(APP_SCHEMA) != null) {
intent.setPackage((String) options.argument(APP_SCHEMA));
return intent;
}

return intent;
}

Expand Down
37 changes: 11 additions & 26 deletions example/android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,37 +1,26 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'dev.flutter.flutter-gradle-plugin'
}

def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) }
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw 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 from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def flutterVersionCode = localProperties.getProperty('flutter.versionCode') ?: '1'
def flutterVersionName = localProperties.getProperty('flutter.versionName') ?: '1.0'

android {
compileSdk = 35
compileSdk = 36
namespace 'com.dataxad.flutter_mailer_example'

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.dataxad.flutter_mailer_example"
minSdkVersion flutter.minSdkVersion
minSdkVersion flutter.minSdkVersion
targetSdkVersion 35
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
Expand All @@ -47,10 +36,6 @@ android {
}
}

flutter {
source '../..'
}

dependencies {
testImplementation 'junit:junit:4.12'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// import dev.flutter.plugins.integration_test.IntegrationTestPlugin;
// import io.flutter.plugins.imagepicker.ImagePickerPlugin;
// import io.flutter.plugins.pathprovider.PathProviderPlugin;
import io.flutter.app.FlutterActivity;
import io.flutter.embedding.android.FlutterActivity;

public class EmbeddingV1Activity extends FlutterActivity {
// @Override
Expand Down
16 changes: 0 additions & 16 deletions example/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
buildscript {
ext {
agp_version = '8.7.0'
kotlin_version = '2.1.0'
}
repositories {
google()
mavenCentral()
}

dependencies {
classpath "com.android.tools.build:gradle:$agp_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

allprojects {
repositories {
google()
Expand Down
32 changes: 24 additions & 8 deletions example/android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
include ':app'
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}

def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()

assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
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"
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null : "flutter.sdk not set in local.properties"

// Make the Flutter Gradle plugin available to this build without applying it imperatively.
includeBuild("${flutterSdkPath}/packages/flutter_tools/gradle")
}

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.7.0" apply false
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}

include ":app"
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: flutter_mailer
description: Share an email to device Email - Client supports multiple Attachments
version: 3.0.1
version: 3.0.2
homepage: https://github.com/taljacobson/flutter_mailer

dependencies:
Expand Down