Accessing Native Features
1. Using Platform Detection
| Platform | Check Method | Description |
|---|---|---|
| Android | defaultTargetPlatform == TargetPlatform.android |
Detects if running on Android |
| iOS | defaultTargetPlatform == TargetPlatform.iOS |
Detects if running on iOS |
| Web | defaultTargetPlatform == TargetPlatform.web |
Detects if running on web platform |
| macOS | defaultTargetPlatform == TargetPlatform.macOS |
Detects if running on macOS |
| Windows | defaultTargetPlatform == TargetPlatform.windows |
Detects if running on Windows |
| Linux | defaultTargetPlatform == TargetPlatform.linux |
Detects if running on Linux |
Example: Detecting Platform
import 'package:flutter/foundation.dart';
void main() {
if (defaultTargetPlatform == TargetPlatform.android) {
print("Running on Android");
} else if (defaultTargetPlatform == TargetPlatform.iOS) {
print("Running on iOS");
} else {
print("Running on other platform");
}
}
Note:
defaultTargetPlatform is a constant that provides the current platform at runtime.
2. Using Conditional Rendering
In Flutter, conditional rendering allows you to display or hide widgets based on certain conditions. This is commonly achieved using conditional expressions, such as the ternary operator or if-else statements.
| Condition | Widget | Description |
|---|---|---|
| if (condition) | Widget? child |
Renders child only if the condition is true. Returns null otherwise. |
| if (condition) ... | Widget child |
Used in list contexts to conditionally include widgets. |
Example: Ternary Operator for Conditional Rendering
<Widget> widget = isLoggedIn ? WelcomeScreen() : LoginScreen();
Example: Conditional List Rendering
List<Widget> items = [
if (showHeader) HeaderWidget(),
ItemWidget(data: item),
];
Note: The
if conditional expressions in Flutter are evaluated at build time, so they should not be used for dynamic UI updates. For runtime updates, use setState or state management solutions.
3. Accessing Device Information
| Property | Description | Example |
|---|---|---|
| DeviceInfoPlugin | Plugin to access device information like model, OS version, etc. | DeviceInfoPlugin().platform |
| deviceInfo | Asynchronous method to retrieve device info | await DeviceInfoPlugin().deviceInfo |
| androidInfo | Android-specific device info (requires Android plugin) | await DeviceInfoPlugin().androidInfo |
| iosInfo | iOS-specific device info (requires iOS plugin) | await DeviceInfoPlugin().iosInfo |
Example: Retrieving Device Information
import 'package:device_info_plus/device_info_plus.dart';
void main() async {
final deviceInfo = await DeviceInfoPlugin().deviceInfo;
print('Model: ${deviceInfo.androidInfo?.model}');
print('OS Version: ${deviceInfo.androidInfo?.version}');
}
Note: On iOS, you must add
NSCameraUsageDescription to your Info.plist for some device info access.
Warning: Some device information might not be accessible on all platforms or devices due to privacy restrictions.
4. Implementing Deep Links
| Feature | Description | Implementation |
|---|---|---|
| Deep Link URL | URL that opens the app and navigates to a specific screen | https://myapp.com/screen1?param=value |
| App Scheme | Custom scheme to open the app from a browser or another app | myapp://screen1?param=value |
| Universal Links (iOS) | HTTPS links that can open the app if installed | https://myapp.com/screen1?param=value |
| App Links (Android) | HTTPS links that open the app if installed | https://myapp.com/screen1?param=value |
Example: Handling Deep Links in Flutter
import 'package:flutter/material.dart';
import 'package:firebase_dynamic_links/firebase_dynamic_links.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Deep Link Demo',
home: HomeScreen(),
onGenerateRoute: (settings) {
if (settings.name == '/screen1') {
return MaterialPageRoute(
builder: (context) => Screen1(),
);
}
return null;
},
);
}
}
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late StreamSubscription<PendingDynamicLinkData> _linkStream;
@override
void initState() {
super.initState();
_linkStream = FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLinkData) {
Uri deepLink = dynamicLinkData.link;
// Handle the deep link
Navigator.pushNamed(context, '/screen1');
},
onError: (DynamicLinkError error) {
print("Dynamic Link Error: ${error.message}");
},
);
}
@override
void dispose() {
_linkStream.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Home")),
body: Center(child: Text("Deep Link Demo")),
);
}
}
class Screen1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Screen 1")),
body: Center(child: Text("This is Screen 1")),
);
}
}
Note: Ensure that your app's
AndroidManifest.xml and Info.plist are configured to handle deep links correctly.
Warning: On Android, make sure to set up the
intent-filter in AndroidManifest.xml to capture deep links.
Deep Link Setup Summary
- Define custom schemes or universal links
- Implement
FirebaseDynamicLinksfor handling dynamic links - Configure app manifest files to capture deep links
- Use
navigator.pushNamedto navigate to specific screens
5. Using Camera
| Property | Description | Example |
|---|---|---|
| camera | Access to camera functionality using the camera package |
CameraController controller = CameraController(camera, ResolutionPreset.medium); |
| CameraController | Class to control camera features like start, stop, and capture | await controller.initialize(); |
| CameraDescription | Provides camera details like lens direction and resolution | CameraDescription camera = cameras.first; |
Example: Initialize Camera
import 'package:camera/camera.dart';
Future<List<CameraDescription>> _initCameras() async {
final cameras = await availableCameras();
return cameras;
}
Example: Capture Photo
Future<XFile> takePicture() async {
final image = await controller.takePicture();
return image;
}
Note: Ensure you have added the
camera package to your pubspec.yaml and requested camera permissions in Android/iOS manifests.
6. Using Location Services
| Property | Description | Example |
|---|---|---|
| Geolocator | Plugin for accessing device location | import 'package:geolocator/geolocator.dart'; |
| getCurrentPosition | Get current device location | Position position = await Geolocator.getCurrentPosition(); |
| requestPermission | Request location permission | LocationPermission permission = await Geolocator.requestPermission(); |
Example: Get Current Location
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
class LocationExample extends StatefulWidget {
@override
_LocationExampleState createState() => _LocationExampleState();
}
class _LocationExampleState extends State<LocationExample> {
Position? _currentPosition;
Future<void> _getCurrentLocation() async {
try {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
);
setState(() {
_currentPosition = position;
});
} catch (e) {
print("Error: $e");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Location Example")),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Latitude: ${_currentPosition?.latitude ?? 'N/A'}"),
Text("Longitude: ${_currentPosition?.longitude ?? 'N/A'}"),
ElevatedButton(
onPressed: _getCurrentLocation,
child: Text("Get Location"),
),
],
),
),
);
}
}
Note: Ensure you add the required permissions in AndroidManifest.xml and Info.plist for iOS.
Warning: Location services may not be available on all devices or in all environments.
7. Handling Permissions
| Permission | Android Manifest | iOS Info.plist | Description |
|---|---|---|---|
| android.permission.CAMERA | <uses-permission android:name="android.permission.CAMERA" /> |
<key>NSCameraUsageDescription</key><string>This app needs camera access to take photos.</string> |
Access to device camera for capturing images or videos |
| android.permission.RECORD_AUDIO | <uses-permission android:name="android.permission.RECORD_AUDIO" /> |
<key>NSMicrophoneUsageDescription</key><string>This app uses the microphone for audio recording.</string> |
Permission to record audio using the device microphone |
| android.permission.ACCESS_FINE_LOCATION | <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
<key>NSLocationWhenInUseUsageDescription</key><string>This app uses location to provide services.</string> |
Access to precise location data (GPS) |
| android.permission.ACCESS_COARSE_LOCATION | <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> |
<key>NSLocationWhenInUseUsageDescription</key><string>This app uses location to provide services.</string> |
Access to approximate location data |
| android.permission.WRITE_EXTERNAL_STORAGE | <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> |
<key>UIFileSharingEnabled</key><true/> |
Write to external storage (e.g., SD card) |
| android.permission.READ_CONTACTS | <uses-permission android:name="android.permission.READ_CONTACTS" /> |
<key>NSContactsUsageDescription</key><string>This app accesses contacts to sync data.</string> |
Read contact list from device |
Example: Requesting Camera Permission
import 'package:permission_handler/permission_handler.dart';
Future<void> requestCameraPermission() async {
final status = await Permission.camera.request();
if (status == PermissionStatus.granted) {
// Proceed with camera functionality
} else if (status == PermissionStatus.denied) {
// Show rationale or guide user to settings
} else if (status == PermissionStatus.permanentlyDenied) {
// Guide user to app settings to enable permission
}
}
Note: On Android 6.0 (API level 23) and above, runtime permissions must be requested by the app at runtime. On iOS, you must also provide a usage description in
Info.plist.
Warning: If a permission is denied permanently, the user must manually enable it in system settings. The app cannot request it again.
8. Using Share Functionality
| Property | Description | Example |
|---|---|---|
| Share.share | Shares text, links, or files using the native share sheet | await Share.share('Check out this cool app!'); |
| Share.shareWithText | Shares text with a custom message | await Share.shareWithText('Flutter is awesome!'); |
| Share.shareFiles | Shares files or images with optional text | await Share.shareFiles([File('image.jpg')], subject: 'Check this image'); |
Example: Sharing a URL
import 'package:share_plus/share_plus.dart';
Future<void> shareUrl() async {
await Share.share('https://flutter.dev');
}
Example: Sharing an Image
import 'package:share_plus/share_plus.dart';
import 'dart:io';
Future<void> shareImage() async {
final File image = File('assets/images/flutter_logo.png');
await Share.shareFiles([image.path], subject: 'Flutter Logo');
}
Note: On web, the Share API uses the Web Share API. It may not work in all browsers.
9. Accessing File System
| Method | Description | Return Type | Notes |
|---|---|---|---|
| getTemporaryDirectory() | Gets the temporary directory path | Future<String> |
Used for temporary files that are deleted on app restart |
| getApplicationDocumentsDirectory() | Gets the app's documents directory | Future<String> |
Used for storing app-specific data that persists across sessions |
| getExternalStorageDirectory() | Gets the external storage directory | Future<String> |
DEPRECATED in favor of scoped storage |
Example: Reading a File
import 'dart:io';
import 'package:path_provider/path_provider.dart';
Future<String> readFile() async {
final directory = await getApplicationDocumentsDirectory();
final file = File('${directory.path}/example.txt');
return await file.readAsString();
}
Example: Writing to a File
import 'dart:io';
import 'package:path_provider/path_provider.dart';
Future<void> writeFile() async {
final directory = await getApplicationDocumentsDirectory();
final file = File('${directory.path}/example.txt');
await file.writeAsString('Hello, Flutter!');
}
Note: On Android, you may need to request
READ_EXTERNAL_STORAGE or WRITE_EXTERNAL_STORAGE permissions for external storage access.
Warning: On iOS, files in the app's sandbox are not accessible from outside the app. Use
getApplicationDocumentsDirectory for persistent storage.
10. Using Connectivity Checks
| Property | Description | Usage |
|---|---|---|
| Connectivity | Plugin to check device's network connectivity status | Connectivity().checkConnectivity() |
| ConnectivityResult | Enum representing network connection types | ConnectivityResult.none, ConnectivityResult.wifi, ConnectivityResult.mobile |
Example: Check Connectivity Status
import 'package:connectivity_plus/connectivity_plus.dart';
Future<ConnectivityResult> checkConnectivity() async {
var result = await Connectivity().checkConnectivity();
return result;
}
Note: The
connectivity_plus plugin is the recommended way to check connectivity in Flutter apps.
Warning: Connectivity status can change at any time; always re-check when needed.