VisProfiler SDK for Flutter
A comprehensive, privacy-first device profiling and analytics SDK for Flutter applications that collects device, network, and location data across Android and iOS platforms.
Features
- π Comprehensive Device Profiling: Collect detailed device information including hardware specs, OS version, and device capabilities
- π Advanced Network Analytics: Track network types, connection quality, carrier information, and public IP
- π Privacy-Aware Location Services: Optional location tracking with user consent
- π Privacy-First Approach: All data collection is optional and configurable
- β‘ Performance Optimized: Efficient caching and minimal battery impact
- π± Cross-Platform: Native implementations for both Android and iOS
- π― Advertising Integration: Optional IDFA/GAID collection for attribution
- π Real-Time & Batch Processing: Configurable data transmission modes
Installation
Add visprofiler to your pubspec.yaml:
dependencies:
visprofiler: ^1.0.0
Run the installation command:
flutter pub get
Platform Setup
Android Configuration
1. Update your android/app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package.name">
<!-- Required Permissions -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- Optional Permissions (based on your needs) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- For Advertising ID -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
<application
android:label="your_app_name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<!-- Your existing application configuration -->
</application>
</manifest>
2. Minimum SDK Configuration:
Ensure your android/app/build.gradle has minimum SDK 21:
android {
compileSdk 34
defaultConfig {
minSdk 21 // Required for VisProfiler SDK
targetSdk 34
}
}
Note: Google Play Services dependencies are automatically included by the VisProfiler SDK.
iOS Configuration
1. Update your ios/Runner/Info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<!-- Your existing Info.plist content -->
<!-- Location Permissions (if using location features) -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs location access to provide location-based analytics.</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>This app needs location access to provide comprehensive analytics.</string>
<!-- Network Usage Description (if needed) -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<!-- Privacy Manifest (iOS 17+) -->
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
</dict>
<dict>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>35F9.1</string>
</array>
</dict>
</array>
</dict>
</plist>
2. Add iOS Podfile Configuration:
In your ios/Podfile, ensure you have:
platform :ios, '11.0'
target 'Runner' do
use_frameworks!
use_modular_headers!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
Basic Usage
1. Import the Package
import 'package:visprofiler/visprofiler.dart';
2. Initialize the SDK
void initializeVisProfiler() {
final options = VisProfilerOptions(
enableLocation: true, // Collect location data
enableNetworkInfo: true, // Collect network information
enableAdId: true, // Collect advertising ID
enableDeviceInfo: true, // Collect device information
enablePublicIp: true, // Collect public IP
enablePeriodicSending: true, // Enable automatic data transmission
sendIntervalMs: 60000, // Send data every 60 seconds
enableLogging: true, // Enable debug logging
enableCaching: true, // Enable data caching for performance
);
final success = Visprofiler.instance.init(
'YOUR_APP_ID_HERE', // Replace with your app ID
{
'userId': 'user_123',
'email': 'user@example.com',
'name': 'John Doe',
'subscription': 'premium',
},
options: options,
);
if (success) {
print('VisProfiler SDK initialized successfully');
} else {
print('Failed to initialize VisProfiler SDK');
}
}
3. Send Data Manually
Future<void> sendAnalyticsData() async {
final result = await Visprofiler.instance.sendData({
'event_type': 'user_action',
'screen': 'home',
'action': 'button_click',
'custom_data': {
'feature': 'premium_upgrade',
'timestamp': DateTime.now().toIso8601String(),
},
});
if (result.success) {
print('Data sent successfully: ${result.response}');
} else {
print('Failed to send data: ${result.error}');
}
}
Advanced Configuration
Custom Options
final customOptions = VisProfilerOptions(
// Data Collection Options
enableLocation: true, // GPS coordinates (requires permission)
enableNetworkInfo: true, // Network type, carrier, signal strength
enableAdId: false, // Advertising ID (IDFA/GAID)
enableDeviceInfo: true, // Device specs, OS version
enablePublicIp: true, // External IP address
// Performance Options
enableCaching: true, // Cache data to reduce native calls
// Transmission Options
enablePeriodicSending: true, // Auto-send data at intervals
sendIntervalMs: 30000, // Send every 30 seconds
// Debug Options
enableLogging: false, // Disable in production
);
Permission Management
The SDK automatically handles permission requests, but you can also check/request permissions manually:
// Check current permission status
final permissionStatus = await Visprofiler.instance.checkPermissionStatus();
print('Location permission: ${permissionStatus['location']}');
// Request location permission
final locationPermission = await Visprofiler.instance.requestLocationPermission();
if (locationPermission.isGranted) {
print('Location permission granted');
}
Health Check and Testing
// Perform SDK health check
final healthStatus = await Visprofiler.instance.healthCheck();
print('SDK Health: ${healthStatus}');
// Test native module functionality
final testResults = await Visprofiler.instance.testNativeModule();
print('Module Tests: ${testResults}');
Runtime Configuration Updates
// Update options at runtime
final newOptions = VisProfilerOptions(
enableLocation: false, // Disable location tracking
enablePeriodicSending: false, // Stop automatic sending
enableLogging: false, // Disable logging
);
Visprofiler.instance.updateOptions(newOptions);
Data Types Collected
Device Information
- Device ID (Android ID / IDFV)
- Brand, model, manufacturer
- Operating system and version
- Screen resolution and density
- Memory usage and storage
- Battery level and charging status
- Jailbreak/root detection
- Device capabilities (notch, dynamic island)
Network Information
- Connection type (WiFi, Cellular, Ethernet)
- Network generation (2G, 3G, 4G, 5G)
- Carrier information
- Signal strength and quality
- Public IP address
- VPN detection
- Data usage metrics
Location Information (Optional)
- GPS coordinates (latitude, longitude)
- Location accuracy
- Altitude and speed
- Location provider
- Timestamp
Advertising Information (Optional)
- Advertising ID (IDFA on iOS, GAID on Android)
- Attribution tracking capabilities
Privacy and Compliance
GDPR/CCPA Compliance
- All data collection is opt-in and configurable
- Users can control exactly what data is collected
- No data is collected without explicit permission
- Easy to implement data deletion requests
Data Security
- All data transmission uses HTTPS encryption
- No sensitive personal information is collected by default
- Device identifiers are anonymized where possible
- Local data is securely cached with automatic cleanup
Best Practices
// Example: Privacy-conscious initialization
final privacyOptions = VisProfilerOptions(
enableLocation: false, // Disable location by default
enableAdId: false, // Disable advertising ID
enablePublicIp: false, // Disable public IP collection
enableDeviceInfo: true, // Only collect basic device info
enableNetworkInfo: true, // Network info for performance optimization
enableLogging: false, // Disable logging in production
);
// Initialize with minimal data collection
Visprofiler.instance.init('your_app_id', null, options: privacyOptions);
// Later, request user consent for additional data
void requestEnhancedAnalytics() async {
final userConsent = await showConsentDialog(); // Your consent implementation
if (userConsent) {
final enhancedOptions = VisProfilerOptions(
enableLocation: true,
enableAdId: true,
enablePublicIp: true,
// ... other options
);
Visprofiler.instance.updateOptions(enhancedOptions);
}
}
Error Handling and Debugging
Enable Logging
final debugOptions = VisProfilerOptions(
enableLogging: true, // Enable detailed console logs
);
Handle Errors Gracefully
try {
final result = await Visprofiler.instance.sendData({'event': 'test'});
if (result.success) {
print('Success: ${result.response}');
} else {
print('Error: ${result.error}');
if (result.retryable) {
// Retry the operation later
Timer(Duration(seconds: 30), () {
// Retry logic
});
}
}
} catch (e) {
print('Exception occurred: $e');
}
Performance Monitoring
// Monitor SDK performance
final healthCheck = await Visprofiler.instance.healthCheck();
final cacheStatus = healthCheck['cache'];
final sdkStatus = healthCheck['sdk'];
print('Cache hit rate: Device=${cacheStatus['deviceInfoCached']}, Network=${cacheStatus['networkInfoCached']}');
print('Auto-sending active: ${sdkStatus['hasActiveInterval']}');
Resource Management
Cleanup and Disposal
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void dispose() {
// Stop periodic data transmission
Visprofiler.instance.stopSendingData();
// Clean up SDK resources
Visprofiler.instance.dispose();
super.dispose();
}
}
Troubleshooting
Common Issues
-
"SDK not initialized" Error
// Ensure init() is called before any other SDK methods Visprofiler.instance.init('your_app_id', {}); -
Location Data Not Available
- Check that location permissions are granted
- Ensure location services are enabled on the device
- Verify
enableLocation: truein options
-
Network Data Missing
- Check internet connectivity
- Verify network permissions in AndroidManifest.xml
- Ensure
enableNetworkInfo: truein options
-
iOS Build Issues
- Run
cd ios && pod install --clean-install - Check iOS deployment target is 11.0+
- Verify Info.plist permissions are correctly configured
- Run
-
Android Build Issues
- Check minimum SDK version is 21+
- Verify all required permissions in AndroidManifest.xml
- Ensure Google Play Services dependencies are added
Debug Mode
Enable debug logging to troubleshoot issues:
final debugOptions = VisProfilerOptions(
enableLogging: true,
);
Visprofiler.instance.init('your_app_id', {}, options: debugOptions);
// Check debug output in console for detailed information
API Reference
Core Methods
init(appId, contact, options)- Initialize the SDKsendData(extraPayload)- Send analytics datastopSendingData()- Stop periodic data transmissionupdateOptions(options)- Update configuration at runtimedispose()- Clean up SDK resources
Utility Methods
checkPermissionStatus()- Check current permissionsrequestLocationPermission()- Request location accesshealthCheck()- Get SDK status informationtestNativeModule()- Test native functionality
Properties
isInitialized- Check if SDK is initializedoptions- Get current configurationappId- Get current app ID
Support
For technical support, feature requests, or bug reports:
- GitHub Issues: https://github.com/auvgffle/visprofiler/issues
- Documentation: https://github.com/auvgffle/visprofiler#readme
License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please read the contributing guidelines first.
Changelog
See CHANGELOG.md for release notes and version history.