local_first_gdrive_backup 0.1.0
local_first_gdrive_backup: ^0.1.0 copied to clipboard
Google Drive backup provider for local_first: backup and restore app data using Google Drive App Data folder.
local_first_gdrive_backup #
A Google Drive backup provider for the LocalFirst framework. Backup and restore your local-first data using Google Drive's hidden App Data folder — the same approach used by WhatsApp on Android.
Note: This is a companion package to
local_first. You need to install the core package first.
Why local_first_gdrive_backup? #
- WhatsApp-style backups: Uses the hidden App Data folder, invisible to the user in their Drive
- AES-256 encryption: Backups are encrypted with a user-provided password before upload
- Cross-platform: Works on Android, iOS, and web via Google Sign-In
- Automatic authentication: Built-in Google Sign-In with
drive.appdatascope - Simple API: Upload, download, list, and delete backups with a single method call
- Incremental restore: Restores merge with existing data instead of overwriting
Features #
- ✅ Google Drive App Data Folder: Hidden storage only your app can access
- ✅ Google Sign-In Integration: Built-in authentication flow
- ✅ Upload/Download Backups: Full backup lifecycle management
- ✅ List Available Backups: Browse and select backups to restore
- ✅ Delete Old Backups: Clean up storage when no longer needed
- ✅ Configurable Folder Name: Organize backups in custom subfolders
- ✅ Full Test Coverage: Comprehensive unit tests with mocked Google APIs
Installation #
Add the dependencies to your pubspec.yaml:
dependencies:
local_first: ^0.7.0
local_first_gdrive_backup: ^0.1.0
# Choose your storage adapter
local_first_hive_storage: ^0.2.0 # or
local_first_sqlite_storage: ^0.3.0
Then install:
flutter pub get
Setup #
Android #
Add the following to your android/app/build.gradle:
dependencies {
implementation 'com.google.android.gms:play-services-auth:21.0.0'
}
Configure your OAuth 2.0 Client ID in the Google Cloud Console. Enable the Google Drive API and create an Android OAuth client with your app's SHA-1 fingerprint.
iOS #
Add your GoogleService-Info.plist to the iOS project and configure the URL scheme in Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.googleusercontent.apps.YOUR_CLIENT_ID</string>
</array>
</dict>
</array>
Quick Start #
import 'package:local_first/local_first.dart';
import 'package:local_first_gdrive_backup/local_first_gdrive_backup.dart';
// 1) Create the provider
final gdriveProvider = GDriveBackupProvider(
folderName: 'my_app_backups', // optional, defaults to 'local_first_backups'
);
// 2) Sign in with Google (required before any operation)
await gdriveProvider.signIn();
// 3) Create the backup service
final backupService = BackupService(client: myLocalFirstClient);
// 4) Create a backup
final metadata = await backupService.createBackup(
provider: gdriveProvider,
password: 'user-chosen-password',
);
print('Backup created: ${metadata.fileName} (${metadata.sizeInBytes} bytes)');
// 5) List available backups
final backups = await backupService.listBackups(gdriveProvider);
for (final backup in backups) {
print('${backup.fileName} - ${backup.createdAt}');
}
// 6) Restore from a backup
await backupService.restoreBackup(
provider: gdriveProvider,
metadata: backups.first,
password: 'user-chosen-password',
);
// 7) Delete a backup
await backupService.deleteBackup(
provider: gdriveProvider,
metadata: backups.last,
);
// 8) Sign out when done
await gdriveProvider.signOut();
How It Works #
Backup Flow #
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ LocalFirstClient│────▶│ BackupService │────▶│ GDriveBackup │
│ │ │ │ │ Provider │
│ - repositories │ │ 1. Collect data │ │ │
│ - events │ │ 2. JSON encode │ │ Upload to │
│ - config │ │ 3. Gzip compress │ │ App Data folder │
│ │ │ 4. AES-256 encrypt│ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Restore Flow #
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ GDriveBackup │────▶│ BackupService │────▶│ LocalFirstClient│
│ Provider │ │ │ │ │
│ │ │ 1. AES-256 decrypt│ │ Incremental │
│ Download from │ │ 2. Gunzip │ │ merge via │
│ App Data folder │ │ 3. JSON decode │ │ pullChanges() │
│ │ │ 4. Restore config │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Architecture #
App Data Folder #
Google Drive's App Data folder is a special hidden folder:
- Invisible to users — they won't see backup files in their Drive
- App-scoped — only your app can access its own App Data
- Automatic cleanup — uninstalling the app revokes access (data is retained)
- No quota impact — App Data doesn't count against the user's storage quota
Storage Structure #
Google Drive App Data/
└── local_first_backups/ ← configurable via folderName
├── backup_2026-03-01T12:00:00Z.lfbk
├── backup_2026-03-05T08:30:00Z.lfbk
└── backup_2026-03-09T15:45:00Z.lfbk
Configuration #
Custom Folder Name #
Organize backups in a custom subfolder within App Data:
final provider = GDriveBackupProvider(
folderName: 'production_backups',
);
Sign-In Scopes #
The provider automatically requests the drive.appdata scope, which only grants access to the hidden App Data folder — not the user's files.
Comparison with Other Providers #
| Feature | GDrive | iCloud | Firebase Storage |
|---|---|---|---|
| Platform | Android, iOS, Web | iOS, macOS only | All platforms |
| Auth | Google Sign-In | Automatic (Apple ID) | Firebase Auth |
| Storage Location | App Data folder | iCloud Documents | Firebase Storage |
| User Visibility | Hidden | Visible in iCloud | Hidden |
| Quota Impact | No | Yes (iCloud quota) | Yes (Firebase quota) |
| Best For | Android-first apps | Apple-only apps | Cross-platform apps |
Best Practices #
- Sign in early: Call
signIn()during app initialization so backups are ready when needed - Handle sign-in cancellation:
signIn()throwsStateErrorif the user cancels — show a user-friendly message - Limit backup count: Delete old backups after creating new ones to save storage
- Use strong passwords: The encryption is only as strong as the user's password
- Test restore flow: Always verify backups can be restored before relying on them
Troubleshooting #
Google Sign-In Fails #
- Verify your OAuth 2.0 Client ID is configured correctly
- Check that the Google Drive API is enabled in the Cloud Console
- Ensure the SHA-1 fingerprint matches your app's signing key
Upload Returns Error #
- Check that the user is signed in (
signIn()was called successfully) - Verify internet connectivity
- Check Google Cloud Console for API quota limits
Backups Not Appearing in List #
- Ensure you're using the same
folderNamefor upload and list operations - Verify the Google account is the same one used for upload
Sign-In Scope Issues #
- The provider only requests
drive.appdatascope — if you need broader Drive access, handle it separately - On iOS, ensure the URL scheme is configured in
Info.plist
Testing #
import 'package:flutter_test/flutter_test.dart';
import 'package:googleapis/drive/v3.dart' as drive;
import 'package:local_first_gdrive_backup/local_first_gdrive_backup.dart';
import 'package:mocktail/mocktail.dart';
class MockDriveApi extends Mock implements drive.DriveApi {}
void main() {
test('uploads backup to App Data folder', () async {
final mockApi = MockDriveApi();
final provider = GDriveBackupProvider(driveApi: mockApi);
// ... set up mocks and test
});
}
Contributing #
Contributions are welcome. See CONTRIBUTING.md for guidelines.
Support the Project 💰 #
Your contributions help us enhance and maintain our plugins. Donations are used to procure devices and equipment for testing compatibility across platforms and versions.
License #
This project is available under the MIT License. See LICENSE for details.

