app_info_flutter 2.0.0
app_info_flutter: ^2.0.0 copied to clipboard
A Flutter plugin to retrieve basic app information like name, package name, version, build number, and other app metadata.
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:app_info_flutter/app_info_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _appName = 'Unknown';
String _packageName = 'Unknown';
String _version = 'Unknown';
String _buildNumber = 'Unknown';
String _buildType = 'Unknown';
String _installerPackage = 'Unknown';
String _firstInstallTime = 'Unknown';
String _lastUpdateTime = 'Unknown';
String _appSize = 'Unknown';
String _cacheSize = 'Unknown';
String _targetSdkVersion = 'Unknown';
String _minSdkVersion = 'Unknown';
List<String> _grantedPermissions = [];
List<String> _declaredPermissions = [];
// New features
String _signature = 'Unknown';
List<String> _signatures = [];
String _isPhysicalDevice = 'Unknown';
String _isStoreVersion = 'Unknown';
String _apkSize = 'Unknown';
AppInfoData? _consolidatedAppInfo;
bool _isLoading = false;
final _appInfoFlutterPlugin = AppInfoFlutter();
final _scaffoldMessengerKey = GlobalKey<ScaffoldMessengerState>();
@override
void initState() {
super.initState();
initPlatformState();
}
// Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async {
setState(() {
_isLoading = true;
});
String appName;
String packageName;
String version;
String buildNumber;
String buildType;
String installerPackage;
String firstInstallTime;
String lastUpdateTime;
String appSize;
String cacheSize;
String targetSdkVersion;
String minSdkVersion;
List<String> grantedPermissions = [];
List<String> declaredPermissions = [];
// New features
String signature;
List<String> signatures = [];
String isPhysicalDevice;
String isStoreVersion;
String apkSize;
AppInfoData? consolidatedAppInfo;
try {
appName = await _appInfoFlutterPlugin.getAppName() ?? 'Unknown';
packageName = await _appInfoFlutterPlugin.getPackageName() ?? 'Unknown';
version = await _appInfoFlutterPlugin.getVersion() ?? 'Unknown';
buildNumber = await _appInfoFlutterPlugin.getBuildNumber() ?? 'Unknown';
final buildTypeEnum = await _appInfoFlutterPlugin.getBuildType();
buildType = buildTypeEnum?.name.toUpperCase() ?? 'Unknown';
installerPackage =
await _appInfoFlutterPlugin.getInstallerPackageName() ?? 'Unknown';
final firstInstall = await _appInfoFlutterPlugin.getFirstInstallTime();
firstInstallTime = firstInstall != null
? firstInstall.toString()
: 'Unknown';
final lastUpdate = await _appInfoFlutterPlugin.getLastUpdateTime();
lastUpdateTime = lastUpdate != null ? lastUpdate.toString() : 'Unknown';
final size = await _appInfoFlutterPlugin.getAppSize() ?? 0;
appSize = size > 0
? '${(size / 1024 / 1024).toStringAsFixed(2)} MB'
: 'Unknown';
final cache = await _appInfoFlutterPlugin.getCacheSize() ?? 0;
cacheSize = cache > 0
? '${(cache / 1024 / 1024).toStringAsFixed(2)} MB'
: '$cache Bytes';
final targetSdk = await _appInfoFlutterPlugin.getTargetSdkVersion();
targetSdkVersion = targetSdk?.toString() ?? 'Unknown';
final minSdk = await _appInfoFlutterPlugin.getMinSdkVersion();
minSdkVersion = minSdk?.toString() ?? 'Unknown';
grantedPermissions =
await _appInfoFlutterPlugin.getGrantedPermissions() ?? [];
declaredPermissions =
await _appInfoFlutterPlugin.getDeclaredPermissions() ?? [];
// New features
signature = await _appInfoFlutterPlugin.getSignature() ?? 'None';
signatures = await _appInfoFlutterPlugin.getSignatures() ?? [];
final physicalDev = await _appInfoFlutterPlugin.isPhysicalDevice();
isPhysicalDevice = physicalDev != null
? physicalDev.toString().toUpperCase()
: 'Unknown';
final storeVersion = await _appInfoFlutterPlugin.isStoreVersion();
isStoreVersion = storeVersion != null
? storeVersion.toString().toUpperCase()
: 'Unknown';
final sizeApk = await _appInfoFlutterPlugin.getApkSize() ?? 0;
apkSize = sizeApk > 0
? '${(sizeApk / 1024 / 1024).toStringAsFixed(2)} MB'
: 'Unknown';
consolidatedAppInfo = await _appInfoFlutterPlugin.getAppInfo();
} on PlatformException catch (e) {
appName = 'Failed: ${e.message}';
packageName = 'Failed';
version = 'Failed';
buildNumber = 'Failed';
buildType = 'Failed';
installerPackage = 'Failed';
firstInstallTime = 'Failed';
lastUpdateTime = 'Failed';
appSize = 'Failed';
cacheSize = 'Failed';
targetSdkVersion = 'Failed';
minSdkVersion = 'Failed';
signature = 'Failed';
signatures = [];
isPhysicalDevice = 'Failed';
isStoreVersion = 'Failed';
apkSize = 'Failed';
consolidatedAppInfo = null;
}
if (!mounted) return;
setState(() {
_appName = appName;
_packageName = packageName;
_version = version;
_buildNumber = buildNumber;
_buildType = buildType;
_installerPackage = installerPackage;
_firstInstallTime = firstInstallTime;
_lastUpdateTime = lastUpdateTime;
_appSize = appSize;
_cacheSize = cacheSize;
_targetSdkVersion = targetSdkVersion;
_minSdkVersion = minSdkVersion;
_grantedPermissions = grantedPermissions;
_declaredPermissions = declaredPermissions;
_signature = signature;
_signatures = signatures;
_isPhysicalDevice = isPhysicalDevice;
_isStoreVersion = isStoreVersion;
_apkSize = apkSize;
_consolidatedAppInfo = consolidatedAppInfo;
_isLoading = false;
});
}
Future<void> _handleClearCache() async {
final scaffoldMessenger = _scaffoldMessengerKey.currentState;
if (scaffoldMessenger == null) return;
try {
final success = await _appInfoFlutterPlugin.clearCache();
if (success) {
scaffoldMessenger.showSnackBar(
const SnackBar(content: Text('Cache cleared successfully!')),
);
await initPlatformState();
} else {
scaffoldMessenger.showSnackBar(
const SnackBar(content: Text('Failed to clear cache.')),
);
}
} catch (e) {
scaffoldMessenger.showSnackBar(SnackBar(content: Text('Error: $e')));
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
scaffoldMessengerKey: _scaffoldMessengerKey,
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(
seedColor: Colors.deepPurple,
brightness: Brightness.dark,
),
),
home: Scaffold(
appBar: AppBar(
title: const Text('App Info Plugin Showcase'),
actions: [
IconButton(
icon: _isLoading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.refresh),
onPressed: _isLoading ? null : initPlatformState,
),
],
),
body: _isLoading
? const Center(child: CircularProgressIndicator())
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildInfoCard(
title: 'Basic Info',
icon: Icons.info_outline,
children: [
_buildRow('App Name', _appName),
_buildRow('Package Name', _packageName),
_buildRow('Version', _version),
_buildRow('Build Number', _buildNumber),
],
),
const SizedBox(height: 12),
_buildInfoCard(
title: 'Device & Platform Info',
icon: Icons.phone_android,
children: [
_buildRow('Physical Device?', _isPhysicalDevice),
_buildRow('Store Version?', _isStoreVersion),
_buildRow('Installer Package', _installerPackage),
_buildRow('Build Type', _buildType),
],
),
const SizedBox(height: 12),
_buildInfoCard(
title: 'Storage Details',
icon: Icons.storage,
children: [
_buildRow('App Directory Size', _appSize),
_buildRow('APK File Size', _apkSize),
_buildRow('Cache Directory Size', _cacheSize),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: _handleClearCache,
icon: const Icon(Icons.delete_sweep),
label: const Text('Clear Cache'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.redAccent.withValues(
alpha: 0.2,
),
foregroundColor: Colors.redAccent,
),
),
],
),
const SizedBox(height: 12),
_buildInfoCard(
title: 'SDK & Installation Info',
icon: Icons.settings_applications,
children: [
_buildRow('Target SDK Version', _targetSdkVersion),
_buildRow('Min SDK Version', _minSdkVersion),
_buildRow('First Install Time', _firstInstallTime),
_buildRow('Last Update Time', _lastUpdateTime),
],
),
const SizedBox(height: 12),
_buildInfoCard(
title: 'Security Certificates (SHA-256)',
icon: Icons.security,
children: [
_buildRow('Primary Signature', _signature),
const SizedBox(height: 8),
const Text(
'All Signatures:',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 4),
..._signatures.map(
(sig) => Padding(
padding: const EdgeInsets.only(
left: 8.0,
top: 4.0,
),
child: Text(
sig,
style: const TextStyle(
fontSize: 12,
fontFamily: 'monospace',
),
),
),
),
if (_signatures.isEmpty) const Text('None'),
],
),
const SizedBox(height: 12),
_buildInfoCard(
title: 'Consolidated getAppInfo() Output',
icon: Icons.integration_instructions,
children: [
const Text(
'All metadata returned in a single method channel call:',
style: TextStyle(
fontStyle: FontStyle.italic,
fontSize: 13,
),
),
const SizedBox(height: 8),
Container(
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6),
),
child: Text(
_consolidatedAppInfo != null
? const JsonEncoder.withIndent(
' ',
).convert(_consolidatedAppInfo!.toMap())
: 'No Consolidated Info Available',
style: const TextStyle(
fontSize: 12,
fontFamily: 'monospace',
),
),
),
],
),
const SizedBox(height: 12),
_buildInfoCard(
title: 'Permissions',
icon: Icons.vpn_key,
children: [
const Text(
'Granted:',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 4),
..._grantedPermissions.map((p) => Text('• $p')),
if (_grantedPermissions.isEmpty) const Text('None'),
const SizedBox(height: 12),
const Text(
'Declared in Manifest:',
style: TextStyle(fontWeight: FontWeight.bold),
),
const SizedBox(height: 4),
..._declaredPermissions.map((p) => Text('• $p')),
if (_declaredPermissions.isEmpty) const Text('None'),
],
),
],
),
),
),
),
);
}
Widget _buildInfoCard({
required String title,
required IconData icon,
required List<Widget> children,
}) {
return Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
children: [
Icon(icon, color: Colors.deepPurpleAccent),
const SizedBox(width: 8),
Text(
title,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
],
),
const Divider(),
const SizedBox(height: 4),
...children,
],
),
),
);
}
Widget _buildRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 2,
child: Text(
label,
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
Expanded(
flex: 3,
child: Text(
value,
textAlign: TextAlign.right,
style: const TextStyle(color: Colors.white70),
),
),
],
),
);
}
}