native_android_path 0.0.2
native_android_path: ^0.0.2 copied to clipboard
A Flutter plugin that provides access to various storage paths on Android devices.
NativeAndroidPath #
A Flutter plugin that provides access to various storage paths on Android devices.
Installation #
Add this to your package's pubspec.yaml
file:
dependencies:
native_android_path: ^latest_version
dependencies:
native_android_path: ^0.0.2
Then run:
flutter pub get add native_android_path
Usage #
Import the package:
import 'package:native_android_path/native_android_path.dart';
Create an instance of the NativeAndroidPath
class:
final nativeAndroidPath = NativeAndroidPath();
Methods #
getPlatformVersion()
#
Returns the version of the Android platform.
Example:
Future<void> getAndroidVersion() async {
try {
String? version = await NativeAndroidPath().getPlatformVersion();
print('Android version: $version');
} catch (e) {
print('Error getting Android version: $e');
}
}
getAllPaths()
#
Returns all available storage paths on the device as a map.
Example:
Future<void> showAllPaths() async {
try {
Map<String, String?> paths = await NativeAndroidPath().getAllPaths();
paths.forEach((key, value) {
print('$key: $value');
});
} catch (e) {
print('Error getting all paths: $e');
}
}
getInternalStoragePath()
#
Returns the path to the internal storage directory.
Example:
Future<void> showInternalStorage() async {
try {
String? path = await NativeAndroidPath().getInternalStoragePath();
print('Internal storage path: $path');
} catch (e) {
print('Error getting internal storage path: $e');
}
}
getExternalStoragePath()
#
Returns the path to the external storage directory.
Example:
Future<void> showExternalStorage() async {
try {
String? path = await NativeAndroidPath().getExternalStoragePath();
print('External storage path: $path');
} catch (e) {
print('Error getting external storage path: $e');
}
}
getInternalCachePath()
#
Returns the path to the internal cache directory.
Example:
Future<void> showInternalCache() async {
try {
String? path = await NativeAndroidPath().getInternalCachePath();
print('Internal cache path: $path');
} catch (e) {
print('Error getting internal cache path: $e');
}
}
getExternalCachePath()
#
Returns the path to the external cache directory.
Example:
Future<void> showExternalCache() async {
try {
String? path = await NativeAndroidPath().getExternalCachePath();
print('External cache path: $path');
} catch (e) {
print('Error getting external cache path: $e');
}
}
getDownloadPath()
#
Returns the path to the downloads directory.
Example:
Future<void> showDownloadsFolder() async {
try {
String? path = await NativeAndroidPath().getDownloadPath();
print('Downloads path: $path');
} catch (e) {
print('Error getting downloads path: $e');
}
}
getDCIMPath()
#
Returns the path to the DCIM directory (camera photos).
Example:
Future<void> showDCIMFolder() async {
try {
String? path = await NativeAndroidPath().getDCIMPath();
print('DCIM path: $path');
} catch (e) {
print('Error getting DCIM path: $e');
}
}
getPicturesPath()
#
Returns the path to the pictures directory.
Example:
Future<void> showPicturesFolder() async {
try {
String? path = await NativeAndroidPath().getPicturesPath();
print('Pictures path: $path');
} catch (e) {
print('Error getting pictures path: $e');
}
}
getMoviesPath()
#
Returns the path to the movies directory.
Example:
Future<void> showMoviesFolder() async {
try {
String? path = await NativeAndroidPath().getMoviesPath();
print('Movies path: $path');
} catch (e) {
print('Error getting movies path: $e');
}
}
getMusicPath()
#
Returns the path to the music directory.
Example:
Future<void> showMusicFolder() async {
try {
String? path = await NativeAndroidPath().getMusicPath();
print('Music path: $path');
} catch (e) {
print('Error getting music path: $e');
}
}
getRingtonesPath()
#
Returns the path to the ringtones directory.
Example:
Future<void> showRingtonesFolder() async {
try {
String? path = await NativeAndroidPath().getRingtonesPath();
print('Ringtones path: $path');
} catch (e) {
print('Error getting ringtones path: $e');
}
}
getAlarmsPath()
#
Returns the path to the alarms directory.
Example:
Future<void> showAlarmsFolder() async {
try {
String? path = await NativeAndroidPath().getAlarmsPath();
print('Alarms path: $path');
} catch (e) {
print('Error getting alarms path: $e');
}
}
getNotificationsPath()
#
Returns the path to the notifications directory.
Example:
Future<void> showNotificationsFolder() async {
try {
String? path = await NativeAndroidPath().getNotificationsPath();
print('Notifications path: $path');
} catch (e) {
print('Error getting notifications path: $e');
}
}
getDocumentsPath()
#
Returns the path to the documents directory.
Example:
Future<void> showDocumentsFolder() async {
try {
String? path = await NativeAndroidPath().getDocumentsPath();
print('Documents path: $path');
} catch (e) {
print('Error getting documents path: $e');
}
}
isExternalStorageWritable()
#
Checks if external storage is writable.
Example:
Future<void> checkExternalStorageWritable() async {
try {
bool isWritable = await NativeAndroidPath().isExternalStorageWritable();
print('External storage is writable: $isWritable');
} catch (e) {
print('Error checking if external storage is writable: $e');
}
}
isExternalStorageReadable()
#
Checks if external storage is readable.
Example:
Future<void> checkExternalStorageReadable() async {
try {
bool isReadable = await NativeAndroidPath().isExternalStorageReadable();
print('External storage is readable: $isReadable');
} catch (e) {
print('Error checking if external storage is readable: $e');
}
}
getExternalStorageDirectories(String type)
#
Returns a list of external storage directory paths for the specified type.
Example:
Future<void> getSpecificExternalDirectories() async {
try {
// Possible types: "music", "pictures", "movies", "documents", etc.
List<String> paths = await NativeAndroidPath().getExternalStorageDirectories("pictures");
print('External picture directories:');
for (String path in paths) {
print('- $path');
}
} catch (e) {
print('Error getting external directories: $e');
}
}
Full Example #
Here's a complete example showing how to use multiple methods:
import 'package:flutter/material.dart';
import 'package:native_android_path/native_android_path.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final NativeAndroidPath _pathPlugin = NativeAndroidPath();
Map<String, String> _paths = {};
bool _isLoading = true;
@override
void initState() {
super.initState();
_loadPaths();
}
Future<void> _loadPaths() async {
try {
Map<String, String?> allPaths = await _pathPlugin.getAllPaths();
bool isWritable = await _pathPlugin.isExternalStorageWritable();
bool isReadable = await _pathPlugin.isExternalStorageReadable();
setState(() {
_paths = {
...allPaths.map((key, value) => MapEntry(key, value ?? 'Not available')),
'External storage writable': isWritable.toString(),
'External storage readable': isReadable.toString(),
};
_isLoading = false;
});
} catch (e) {
setState(() {
_paths = {'Error': e.toString()};
_isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Android Storage Paths'),
),
body: _isLoading
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: _paths.length,
itemBuilder: (context, index) {
String key = _paths.keys.elementAt(index);
String value = _paths[key]!;
return ListTile(
title: Text(key),
subtitle: Text(value),
);
},
),
),
);
}
}
Permissions #
For Android 10 (API level 29) and above, you might need to add:
<application
android:requestLegacyExternalStorage="true"
>
For Android 11 (API level 30) and above, consider implementing more specific storage access using the Storage Access Framework or Media Store API.
Required Permissions for Android 13 #
-
General Permissions:
- To access external files, you still need the
READ_EXTERNAL_STORAGE
andWRITE_EXTERNAL_STORAGE
permissions.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- To access external files, you still need the
-
Specific Permissions for Android 13:
- In Android 13, access to media files (such as photos, videos, and music) is controlled separately. To access these files, you must use specific permissions:
READ_MEDIA_IMAGES
: For accessing photos.READ_MEDIA_VIDEO
: For accessing videos.READ_MEDIA_AUDIO
: For accessing audio files.
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
- In Android 13, access to media files (such as photos, videos, and music) is controlled separately. To access these files, you must use specific permissions:
-
Requesting Permissions at Runtime:
- In Android 13, you must request specific permissions at runtime from the user. This is done using
ActivityResultContracts.RequestPermission
orActivityResultContracts.RequestMultiplePermissions
.
Example of requesting permission to access photos:
import 'package:flutter/material.dart'; import 'package:permission_master/permission_master.dart'; Future<void> requestMediaPermissions() async { final permissionMaster = PermissionMaster(); final status = await permissionMaster.requestStoragePermission(); if (status == PermissionStatus.granted) { print('Media permissions granted'); } else if (status == PermissionStatus.openSettings) { // Permanent denial, suggest opening app settings await permissionMaster.openAppSettings(); } else { print('Media permissions denied'); } }
- In Android 13, you must request specific permissions at runtime from the user. This is done using
AndroidManifest.xml
Settings for Android 13 #
To support Android 13, your AndroidManifest.xml
file should look like this:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.yourapp">
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<application
android:requestLegacyExternalStorage="true"
android:label="Your App"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Important Changes for Android 13 #
-
Removal of
requestLegacyExternalStorage
:- In Android 11 (API level 30) and above, the
requestLegacyExternalStorage
attribute was used to maintain compatibility with the old file system. However, in Android 13, this attribute is no longer supported, and you must use specific permissions instead.
- In Android 11 (API level 30) and above, the
-
Use of
MediaStore
:- To access media files in Android 13, you must use
MediaStore
. This API allows you to access photo, video, and music files.
- To access media files in Android 13, you must use
Requesting Permissions at Runtime #
To request permissions at runtime, you can use the permission_master
package. This package helps you request and manage permissions easily.
Setup and Initialization
-
Import the Package
import 'package:permission_master/permission_master.dart';
-
Set BuildContext (Important for Dialogs)
class _MyAppState extends State<MyApp> { @override void initState() { super.initState(); // Set context for dialog support PermissionMaster.setContext(context); } }
Storage Permission Example
Future<void> requestStorageAccess() async {
final permissionMaster = PermissionMaster();
final status = await permissionMaster.requestStoragePermission();
if (status == PermissionStatus.granted) {
// Read/write files allowed
} else if (status == PermissionStatus.openSettings) {
// Permanent denial, suggest opening app settings
await permissionMaster.openAppSettings();
} else {
print('Storage permission not granted');
}
}
Adding Dependencies
In your pubspec.yaml
file, add the package:
dependencies:
permission_master:
git:
url: https://github.com/SwanFlutter/permission_master.git
Note
If you use permission_master
, you still need to add the necessary permissions to the AndroidManifest.xml
file. Also, the android:requestLegacyExternalStorage="true"
attribute should still be included in the application tag.