plugin_volume_info 0.0.6
plugin_volume_info: ^0.0.6 copied to clipboard
A plugin to analyse the volumes of an android device. It includes used, free and total space and also some useful device information like device name, android version. It can also handle copying large files.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
/// Using of plugin
import 'package:plugin_volume_info/volume_info.dart';
/// State of example page
class ExamplePage extends StatefulWidget {
const ExamplePage({super.key, required this.title});
final String title;
@override
State<ExamplePage> createState() => ExamplePageState();
}
/// Example page with detailed information about device
class ExamplePageState extends State<ExamplePage> {
final VolumeInfo _volumeInfoPlugin = VolumeInfo();
late final Map<String, VolumeSpace> _volumesDetails = <String, VolumeSpace>{};
late final int? _androidVersion;
late final String? _deviceName;
late List<FileInfo>? _fileInfos;
@override
void initState() {
loadVolumes();
super.initState();
}
Future<void> loadVolumes() async {
_volumesDetails.clear();
List<String>? volumes = await _volumeInfoPlugin.getVolumesUUIDs(true, true);
for (var uuid in volumes!) {
VolumeSpace volumeSpace = (await _volumeInfoPlugin.getVolumeSpace(uuid))!;
_volumesDetails[uuid] = volumeSpace;
}
_androidVersion = await _volumeInfoPlugin.getAndroidVersion();
_deviceName = await _volumeInfoPlugin.getDeviceName();
_fileInfos = await _volumeInfoPlugin.getVolumeFilesPrimary();
setState(() {});
}
Future<bool?> volumeExists(String uuid) async {
return await _volumeInfoPlugin.isVolumeAvailable(uuid);
}
Widget loadRemoveable() {
if (_volumesDetails.isEmpty) {
return const ListTile(title: Text("Detecting removeable volume..."));
}
// Use first removeable volume for check
String volume2Check = "";
for (var uuid in _volumesDetails.keys) {
if (_volumesDetails[uuid]!.isRemoveable) {
volume2Check = uuid;
break;
}
}
return FutureBuilder(
future: volumeExists(volume2Check),
builder: (ctx, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return ListTile(
title: Text(
'${snapshot.error} occurred',
style: const TextStyle(fontSize: 18),
));
} else if (snapshot.hasData) {
final data = snapshot.data as bool;
if (data == true) {
return const ListTile(
title: Text(
"Removeable volume is available",
style: TextStyle(fontSize: 20, color: Colors.lightGreen),
));
} else {
return const ListTile(
title: Text(
"Removeable volume does not exist",
style: TextStyle(fontSize: 20, color: Colors.redAccent),
));
}
}
}
// Displaying LoadingSpinner to indicate waiting state
return const Center(
child: CircularProgressIndicator(),
);
},
);
}
Widget loadDetails() {
if (_volumesDetails.isEmpty) {
return const Column(
children: [Text("Please wait...")],
);
}
// Build a list of information
List<Widget> children = [];
children.add(ListTile(
title: Text("Volume info's:", style: TextStyle(color: Colors.green))));
children.add(Text("Android version: ${_androidVersion.toString()}"));
children.add(Text("Device name: ${_deviceName.toString()}"));
for (var uuid in _volumesDetails.keys) {
children.add(Text("Volumes UUID: $uuid"));
children.add(Text("Path: ${_volumesDetails[uuid]!.absolutePath}"));
children.add(Text("State: ${_volumesDetails[uuid]!.state}"));
if (_volumesDetails[uuid]!.isPrimary == true) {
children.add(const Text("Primary volume"));
} else {
children.add(const Text("Other volume"));
}
if (_volumesDetails[uuid]!.isRemoveable == true) {
children.add(const Text("Removeable volume"));
} else {
children.add(const Text("Non removeable volume"));
}
children
.add(Text("Total: ${_volumesDetails[uuid]!.totalInGB.round()} GB"));
children.add(Text("Free: ${_volumesDetails[uuid]!.freeInGB.round()} GB"));
children.add(Text("Used: ${_volumesDetails[uuid]!.usedInGB.round()} GB"));
children.add(const Text("---------------------------------"));
}
if (_fileInfos == null) {
children.add(ListTile(title: Text("No files found on primary device")));
} else {
children.add(ListTile(
title: Text("Files found on primary device: <${_fileInfos!.length}>",
style: TextStyle(color: Colors.green))));
List<Widget> filesList = [];
for (FileInfo fileInfo in _fileInfos!) {
filesList.add(ListTile(
title: Text(fileInfo.fileName),
trailing: Text("${fileInfo.fileSize.toString()} Bytes"),
));
}
Widget fileListCol = Column(
children: filesList,
);
Widget fileListScrollable = SizedBox(
height: 200, child: SingleChildScrollView(child: fileListCol));
children.add(fileListScrollable);
}
return Column(
children: children,
);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text(
'plugin_volume_info\nExample for EDAS',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.orangeAccent,
),
),
),
body: SingleChildScrollView(
child: Column(
children: [
loadRemoveable(),
loadDetails(),
],
)),
),
);
}
}
/// State of permission page
class PermissionHandlerScreen extends StatefulWidget {
const PermissionHandlerScreen({super.key, required this.title});
final String title;
@override
State<PermissionHandlerScreen> createState() =>
_PermissionHandlerScreenState();
}
/// Permission page for getting required access
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
final _volumeInfoPlugin = VolumeInfo();
@override
void initState() {
super.initState();
permissionServiceCall();
}
Future<int> getSDKVersion() async {
return await _volumeInfoPlugin.getAndroidVersion() ?? 0;
}
permissionServiceCall() async {
await permissionServices().then((value) {
bool allPermissionsGranted = true;
for (var permission in value.keys) {
if (value[permission]!.isGranted == false) {
allPermissionsGranted = false;
break;
}
}
if (allPermissionsGranted) {
if (mounted) {
Navigator.pushReplacementNamed(context, Routes.example);
}
}
});
}
Future<Map<Permission, PermissionStatus>> permissionServices() async {
Map<Permission, PermissionStatus> permissionStates;
// Special case Android <= V32
if (await getSDKVersion() <= 32) {
permissionStates = await [
Permission.storage,
].request();
} else {
permissionStates = await [
Permission.accessMediaLocation,
Permission.mediaLibrary,
Permission.manageExternalStorage,
Permission.photos,
Permission.videos,
Permission.audio,
Permission.bluetoothConnect
].request();
}
// Check all states
for (var permission in permissionStates.keys) {
if (permissionStates[permission]!.isPermanentlyDenied) {
openAppSettings();
} else {
if (permissionStates[permission]!.isDenied) {
permissionServiceCall();
}
}
}
return permissionStates;
}
@override
Widget build(BuildContext context) {
return PopScope(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) async {
Navigator.of(context).pop();
},
child: Scaffold(
body: Center(
child: InkWell(
onTap: () {
permissionServiceCall();
},
child: Text("Click here to grant the permissions")),
),
),
);
}
}
/// Routing names of pages
class Routes {
static const String permission = '/';
static const String example = '/example';
}
/// Routing of pages
class PageRoutes {
/// when the app is opened this page will be the first to be shown
static const initial = Routes.permission;
static final routes = [
GetPage(
name: Routes.permission,
page: () => const PermissionHandlerScreen(title: "Permissions"),
),
GetPage(
name: Routes.example,
page: () => const ExamplePage(title: "Example"),
),
];
}
/// Example application to show usage of plugin
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: "Example application",
initialRoute: PageRoutes.initial,
getPages: PageRoutes.routes,
);
}
}
void main() {
runApp(const ExampleApp());
}