Flutter Microsoft Azure
Integrate Azure cloud services with Flutter apps
โ๏ธ What is Microsoft Azure?
Microsoft Azure is a comprehensive cloud computing platform offering authentication, databases, storage, AI services, and more. Integrate Azure services into your Flutter apps for enterprise-grade security, scalability, and powerful cloud capabilities.
// Azure authentication example
import 'package:aad_oauth/aad_oauth.dart';
final config = Config(
tenant: 'YOUR_TENANT_ID',
clientId: 'YOUR_CLIENT_ID',
redirectUri: 'YOUR_REDIRECT_URI',
);
final oauth = AadOAuth(config);
await oauth.login();
Key Azure Services
Azure AD Authentication
Enterprise identity and access management with Azure Active Directory. Secure single sign-on, multi-factor authentication, and integration with Microsoft 365 for corporate app development.
final oauth = AadOAuth(config);
await oauth.login();
Cosmos DB
Globally distributed NoSQL database with multiple APIs. Store and query data with low latency worldwide, supporting MongoDB, SQL, Cassandra, and Gremlin APIs for flexible data models.
final response = await http.post(
Uri.parse(cosmosEndpoint),
headers: {'Authorization': token},
);
Blob Storage
Scalable object storage for unstructured data. Store images, videos, backups, and documents with high availability, automatic tiering, and built-in CDN for fast global access.
await azureStorage.uploadBlob(
containerName: 'images',
blobName: 'photo.jpg',
);
Cognitive Services
AI-powered APIs for vision, speech, and language. Add image recognition, text translation, sentiment analysis, and speech-to-text capabilities to your Flutter apps with pre-trained models.
final result = await cognitiveServices
.analyzeImage(imageUrl);
๐น Azure AD Authentication Setup
Implement Microsoft authentication in your Flutter app:
# pubspec.yaml
dependencies:
flutter:
sdk: flutter
aad_oauth: ^0.4.0
http: ^1.1.0
// auth_service.dart
import 'package:aad_oauth/aad_oauth.dart';
import 'package:aad_oauth/model/config.dart';
class AzureAuthService {
static final Config config = Config(
tenant: 'YOUR_TENANT_ID',
clientId: 'YOUR_CLIENT_ID',
scope: 'openid profile offline_access',
redirectUri: 'msauth://com.example.app/callback',
navigatorKey: navigatorKey,
);
final AadOAuth oauth = AadOAuth(config);
Future<bool> login() async {
try {
await oauth.login();
final accessToken = await oauth.getAccessToken();
return accessToken != null;
} catch (e) {
print('Login error: $e');
return false;
}
}
Future<void> logout() async {
try {
await oauth.logout();
} catch (e) {
print('Logout error: $e');
}
}
Future<String?> getAccessToken() async {
try {
return await oauth.getAccessToken();
} catch (e) {
print('Get token error: $e');
return null;
}
}
Future<bool> isLoggedIn() async {
final token = await getAccessToken();
return token != null;
}
}
// Usage in a widget
class AzureLoginScreen extends StatefulWidget {
@override
_AzureLoginScreenState createState() => _AzureLoginScreenState();
}
class _AzureLoginScreenState extends State<AzureLoginScreen> {
final authService = AzureAuthService();
bool isLoading = false;
Future<void> handleLogin() async {
setState(() => isLoading = true);
final success = await authService.login();
setState(() => isLoading = false);
if (success) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => HomeScreen()),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Login failed')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Azure Login')),
body: Center(
child: isLoading
? CircularProgressIndicator()
: ElevatedButton.icon(
onPressed: handleLogin,
icon: Icon(Icons.login),
label: Text('Sign in with Microsoft'),
),
),
);
}
}
Setup requirements:
1. Create Azure AD app registration
2. Configure redirect URIs
3. Get tenant ID and client ID
4. Add authentication to Flutter app
๐น Azure Blob Storage
Upload and download files to Azure Blob Storage:
# pubspec.yaml
dependencies:
azure_storage_blobs: ^0.1.0
http: ^1.1.0
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:crypto/crypto.dart';
import 'dart:convert';
class AzureBlobService {
final String accountName;
final String accountKey;
final String containerName;
AzureBlobService({
required this.accountName,
required this.accountKey,
required this.containerName,
});
String get baseUrl => 'https://$accountName.blob.core.windows.net';
// Upload blob
Future<bool> uploadBlob(String blobName, File file) async {
try {
final bytes = await file.readAsBytes();
final url = '$baseUrl/$containerName/$blobName';
final response = await http.put(
Uri.parse(url),
headers: {
'x-ms-blob-type': 'BlockBlob',
'x-ms-version': '2021-08-06',
'Content-Type': 'application/octet-stream',
'Authorization': _generateAuthHeader('PUT', blobName),
},
body: bytes,
);
return response.statusCode == 201;
} catch (e) {
print('Upload error: $e');
return false;
}
}
// Download blob
Future<List<int>?> downloadBlob(String blobName) async {
try {
final url = '$baseUrl/$containerName/$blobName';
final response = await http.get(
Uri.parse(url),
headers: {
'x-ms-version': '2021-08-06',
'Authorization': _generateAuthHeader('GET', blobName),
},
);
if (response.statusCode == 200) {
return response.bodyBytes;
}
return null;
} catch (e) {
print('Download error: $e');
return null;
}
}
// List blobs
Future<List<String>> listBlobs() async {
try {
final url = '$baseUrl/$containerName?restype=containerโ=list';
final response = await http.get(
Uri.parse(url),
headers: {
'x-ms-version': '2021-08-06',
'Authorization': _generateAuthHeader('GET', ''),
},
);
if (response.statusCode == 200) {
// Parse XML response to get blob names
// Simplified - actual implementation needs XML parsing
return [];
}
return [];
} catch (e) {
print('List error: $e');
return [];
}
}
// Delete blob
Future<bool> deleteBlob(String blobName) async {
try {
final url = '$baseUrl/$containerName/$blobName';
final response = await http.delete(
Uri.parse(url),
headers: {
'x-ms-version': '2021-08-06',
'Authorization': _generateAuthHeader('DELETE', blobName),
},
);
return response.statusCode == 202;
} catch (e) {
print('Delete error: $e');
return false;
}
}
String _generateAuthHeader(String method, String blobName) {
// Simplified - actual implementation needs proper signature
return 'SharedKey $accountName:$accountKey';
}
}
// Usage example
class BlobUploadScreen extends StatelessWidget {
final blobService = AzureBlobService(
accountName: 'YOUR_ACCOUNT_NAME',
accountKey: 'YOUR_ACCOUNT_KEY',
containerName: 'images',
);
Future<void> uploadImage() async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) {
final file = File(image.path);
final blobName = 'image_${DateTime.now().millisecondsSinceEpoch}.jpg';
final success = await blobService.uploadBlob(blobName, file);
if (success) {
print('Upload successful!');
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Azure Blob Storage')),
body: Center(
child: ElevatedButton(
onPressed: uploadImage,
child: Text('Upload Image'),
),
),
);
}
}
๐น Azure Cosmos DB Integration
Connect to Cosmos DB for NoSQL data storage:
import 'package:http/http.dart' as http;
import 'dart:convert';
class CosmosDBService {
final String endpoint;
final String masterKey;
final String databaseId;
final String containerId;
CosmosDBService({
required this.endpoint,
required this.masterKey,
required this.databaseId,
required this.containerId,
});
// Create document
Future<Map<String, dynamic>?> createDocument(
Map<String, dynamic> document,
) async {
try {
final url = '$endpoint/dbs/$databaseId/colls/$containerId/docs';
final response = await http.post(
Uri.parse(url),
headers: {
'Content-Type': 'application/json',
'x-ms-version': '2018-12-31',
'x-ms-documentdb-partitionkey': '["${document['id']}"]',
'Authorization': _generateAuthToken('POST', 'docs', containerId),
},
body: jsonEncode(document),
);
if (response.statusCode == 201) {
return jsonDecode(response.body);
}
return null;
} catch (e) {
print('Create error: $e');
return null;
}
}
// Query documents
Future<List<Map<String, dynamic>>> queryDocuments(String query) async {
try {
final url = '$endpoint/dbs/$databaseId/colls/$containerId/docs';
final response = await http.post(
Uri.parse(url),
headers: {
'Content-Type': 'application/query+json',
'x-ms-version': '2018-12-31',
'x-ms-documentdb-isquery': 'true',
'Authorization': _generateAuthToken('POST', 'docs', containerId),
},
body: jsonEncode({
'query': query,
}),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return List<Map<String, dynamic>>.from(data['Documents']);
}
return [];
} catch (e) {
print('Query error: $e');
return [];
}
}
// Update document
Future<bool> updateDocument(
String documentId,
Map<String, dynamic> document,
) async {
try {
final url = '$endpoint/dbs/$databaseId/colls/$containerId/docs/$documentId';
final response = await http.put(
Uri.parse(url),
headers: {
'Content-Type': 'application/json',
'x-ms-version': '2018-12-31',
'x-ms-documentdb-partitionkey': '["$documentId"]',
'Authorization': _generateAuthToken('PUT', 'docs', containerId),
},
body: jsonEncode(document),
);
return response.statusCode == 200;
} catch (e) {
print('Update error: $e');
return false;
}
}
// Delete document
Future<bool> deleteDocument(String documentId) async {
try {
final url = '$endpoint/dbs/$databaseId/colls/$containerId/docs/$documentId';
final response = await http.delete(
Uri.parse(url),
headers: {
'x-ms-version': '2018-12-31',
'x-ms-documentdb-partitionkey': '["$documentId"]',
'Authorization': _generateAuthToken('DELETE', 'docs', containerId),
},
);
return response.statusCode == 204;
} catch (e) {
print('Delete error: $e');
return false;
}
}
String _generateAuthToken(String verb, String resourceType, String resourceId) {
// Simplified - actual implementation needs proper HMAC signature
return 'type=master&ver=1.0&sig=$masterKey';
}
}
// Usage example
final cosmosDB = CosmosDBService(
endpoint: 'https://YOUR_ACCOUNT.documents.azure.com:443',
masterKey: 'YOUR_MASTER_KEY',
databaseId: 'myDatabase',
containerId: 'myContainer',
);
// Create a user
await cosmosDB.createDocument({
'id': '1',
'name': 'John Doe',
'email': '[email protected]',
});
// Query users
final users = await cosmosDB.queryDocuments(
'SELECT * FROM c WHERE c.name = "John Doe"',
);
๐น Azure Cognitive Services
Add AI capabilities with Computer Vision API:
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:io';
class AzureCognitiveServices {
final String endpoint;
final String subscriptionKey;
AzureCognitiveServices({
required this.endpoint,
required this.subscriptionKey,
});
// Analyze image
Future<Map<String, dynamic>?> analyzeImage(File imageFile) async {
try {
final url = '$endpoint/vision/v3.2/analyze?visualFeatures=Categories,Description,Tags,Objects';
final bytes = await imageFile.readAsBytes();
final response = await http.post(
Uri.parse(url),
headers: {
'Content-Type': 'application/octet-stream',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: bytes,
);
if (response.statusCode == 200) {
return jsonDecode(response.body);
}
return null;
} catch (e) {
print('Analysis error: $e');
return null;
}
}
// Detect text in image (OCR)
Future<String?> detectText(File imageFile) async {
try {
final url = '$endpoint/vision/v3.2/ocr';
final bytes = await imageFile.readAsBytes();
final response = await http.post(
Uri.parse(url),
headers: {
'Content-Type': 'application/octet-stream',
'Ocp-Apim-Subscription-Key': subscriptionKey,
},
body: bytes,
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
// Extract text from regions
return _extractTextFromOCR(data);
}
return null;
} catch (e) {
print('OCR error: $e');
return null;
}
}
String _extractTextFromOCR(Map<String, dynamic> data) {
final regions = data['regions'] as List;
final textLines = <String>[];
for (var region in regions) {
final lines = region['lines'] as List;
for (var line in lines) {
final words = line['words'] as List;
final lineText = words.map((w) => w['text']).join(' ');
textLines.add(lineText);
}
}
return textLines.join('\n');
}
}
// Usage example
class ImageAnalysisScreen extends StatefulWidget {
@override
_ImageAnalysisScreenState createState() => _ImageAnalysisScreenState();
}
class _ImageAnalysisScreenState extends State<ImageAnalysisScreen> {
final cognitiveServices = AzureCognitiveServices(
endpoint: 'https://YOUR_REGION.api.cognitive.microsoft.com',
subscriptionKey: 'YOUR_SUBSCRIPTION_KEY',
);
String result = '';
Future<void> analyzeImage() async {
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
if (image != null) {
final file = File(image.path);
final analysis = await cognitiveServices.analyzeImage(file);
if (analysis != null) {
setState(() {
result = 'Description: ${analysis['description']['captions'][0]['text']}\n';
result += 'Tags: ${analysis['tags'].map((t) => t['name']).join(', ')}';
});
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Image Analysis')),
body: Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
ElevatedButton(
onPressed: analyzeImage,
child: Text('Analyze Image'),
),
SizedBox(height: 24),
Text(result),
],
),
),
);
}
}