Flutter / Editorial solution guide
Separate missing plugin from denied capability
Locate the failing platform boundary before changing channel names, permissions, or application logic.
Read-only knowledge base · No public comments
Recognize the symptoms
A Dart capability call reports MissingPluginException, a PlatformException, an unsupported-value failure, or an unavailable result. The application may work on one target and fail on another.
A fake adapter test passes, but no real target integration has been exercised. A permission prompt may repeat on rebuild or the interface may label unavailable as a valid zero measurement.
Understand the likely causes
- Target support, native registration, protocol naming, codec types, platform configuration, and user permission are different boundaries. A fix for one does not establish the others.
- A host-side fake bypasses native registration and permission behavior. Hot reload may not apply native configuration changes, while repeated rebuild-time calls can restart prompts.
Classify the first failure
Capture the exact first exception, selected target, build variant, plugin version, and minimal synthetic method call. MissingPluginException commonly points to the absence of a matching handler, but inspect target support and registration before concluding that a permission setting is responsible. A platform-reported error may instead reflect a denied or unavailable capability. A decoded wrong type can indicate a protocol mismatch. Avoid broad cleanup commands as a first response because they can change the environment without establishing which boundary actually failed.
Compare both sides of the protocol
For a custom channel, compare the exact channel name, method identifier, codec-supported argument types, result type, nullability, units, and error categories between Dart and native code. A percent integer and a fractional double are different contracts even if both display a plausible number. For a maintained plugin, follow its documented target configuration instead of inventing a custom channel name to silence an exception. Keep native implementation snippets and configuration under the project’s normal review process; this editorial guide does not execute or provision any platform service.
Validate values without fabricating measurements
Keep unavailable separate from a real zero. The fragment maps a nullable synthetic battery value to an application label and rejects out-of-range data. It can be tested as pure policy without hardware. It deliberately does not catch every exception and convert it to zero, because that would turn a broken protocol into an apparently valid measurement. The adapter should translate known platform failures into documented application categories, while retaining safe diagnostic context for unexpected defects. Do not attach sensitive payloads or credentials to those records.
String batteryText(int? value) {
if (value == null) return 'Unavailable';
if (value < 0 || value > 100) throw const FormatException('Invalid percentage');
return '$value%';
}
// batteryText(null) -> 'Unavailable'
// batteryText(0) -> '0%'
Unavailable and 0% remain distinct outcomes.
Pure mapping does not establish native channel registration, permissions, or real battery availability.
Separate status refresh from permission request
Read permission or capability status at a deliberate lifecycle boundary and request permission only in a comprehensible feature flow. A resumed application may need to refresh status after settings change, but it should not automatically replay an earlier sensitive action. Keep fallback behavior available where the feature permits. Native configuration changes require the documented build workflow in an authorized target host; hot reload alone may be insufficient. Verify every supported target separately because a plugin’s available implementation and permission model can differ between platforms.
Verify the fix
First run the pure unavailable, zero, valid, and invalid-value mapping cases in an isolated compatible Dart host. Then use the project’s authorized target workflow to verify registration, successful capability access, denial, unavailability, and recovery.
Keep separate records for fake policy checks and actual platform integration. This course does not claim a native channel execution, device build, permission interaction, or real capability result.
Keep it from recurring
- Maintain a target support matrix and a narrow adapter with explicit result categories. Trigger capability calls from owned events or lifecycle transitions, and preserve protocol fixtures so native changes cannot silently alter units or null meaning.