Flutter: Publicação Multiplataforma e Revisão de Loja
📋 Pré-requisitos: Você deve ter dominado o seguinte primeiro
- Aula 24: Automação CI/CD
1. O Que Você Vai Aprender
2. Uma História Real de uma Submissão Rejeitada
3. Processo de Publicação Multiplataforma
4. Publicação Android
5. Publicação iOS
6. Publicação Web
7. Conformidade de Privacidade
8. Exemplo Completo: Checklist de Publicação do ShopApp
9. Checklist de Release do ShopApp v1.2.3
Depois que Bob se preparou usando o checklist, tanto a App Store quanto o Google Play passaram na primeira submissão, e a versão Web ficou no ar em 1 hora.
graph TD
REL[Release Process] --> ANDROID2[Android AAB]
REL --> IOS2[iOS IPA]
REL --> WEB2[Web PWA]
ANDROID2 --> PC[Play Console]
IOS2 --> ASC[App Store Connect]
WEB2 --> FH[Firebase Hosting / Vercel]
PC --> REVIEW1[Revisão Google]
ASC --> REVIEW2[Revisão Apple]
REVIEW1 --> LIVE1[No ar no Google Play]
REVIEW2 --> LIVE2[No ar na App Store]
FH --> LIVE3[No ar na Web]
(1) Assinatura e Build
▶ Exemplo: Gerar Keystore
# Gerar keystore de assinatura
keytool -genkey -v -keystore shopapp-release.jks \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias shopapp
# Verificar keystore
keytool -list -v -keystore shopapp-release.jks -alias shopapp
Configuração de Assinatura no build.gradle
// android/app/build.gradle
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
defaultConfig {
applicationId "com.shopapp.app"
minSdkVersion 21
targetSdkVersion 34
versionCode 42
versionName "1.2.3"
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['keyFile'] ? file(keystoreProperties['keyFile']) : null
storePassword keystoreProperties['keyPassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
Build e Publicação
# Build release AAB (Android App Bundle)
flutter build appbundle --release
# Saída: build/app/outputs/bundle/release/app-release.aab
# Build release APK (para testes)
flutter build apk --release
# Upload para o Play Console manualmente ou via CI/CD
(2) Checklist de Lançamento no Play Console
| Item | Requisito |
|---|---|
| ID do Aplicativo | Nome de pacote único com.shopapp.app |
| Arquivo AAB | Bundle de release assinado |
| Ícone | 512x512 PNG |
| Screenshots | 2-8 cada para telefone + tablet de 7 polegadas |
| URL da Política de Privacidade | Deve estar acessível |
| Classificação de conteúdo | Completar questionário IARC |
| Público-alvo | Selecionar faixa etária |
(1) Configuração Apple Developer
| Passo | Ação |
|---|---|
| 1. Registro | Apple Developer Program ($99/ano) |
| 2. Certificado | Criar Distribution Certificate |
| 3. Profile | Criar App Store Provisioning Profile |
| 4. App ID | Registrar Bundle Identifier |
| 5. App Record | Criar app no App Store Connect |
Configuração de Build no Xcode
<!-- ios/Runner/Info.plist -->
`<key>`CFBundleShortVersionString</key>
`<string>`1.2.3</string>
`<key>`CFBundleVersion</key>
`<string>`42</string>
`<key>`NSAppTransportSecurity</key>
`<dict>`
`<key>`NSAllowsArbitraryLoads</key>
`<false/>`
`</dict>`
`<key>`NSUserTrackingUsageDescription</key>
`<string>`Usamos rastreamento para personalizar sua experiência de compra.</string>
Build e Upload
# Build IPA
flutter build ipa --release \
--export-options-plist=ios/ExportOptions.plist
# Saída: build/ios/ipa/shopapp.ipa
# Upload via Xcode ou linha de comando
xcrun altool --upload-app \
--type ios \
--file build/ios/ipa/shopapp.ipa \
--apiKey YOUR_API_KEY \
--apiIssuer YOUR_ISSUER_ID
# Ou via app Transporter
(2) Checklist de Lançamento no App Store Connect
| Bundle ID | Deve corresponder ao projeto Xcode | | Arquivo IPA | Build de release | | Screenshots | 6.7"/6.5"/5.5" três tamanhos | | Vídeo de preview | Opcional, ≤30s | | Descrição | ≤4000 caracteres |
▶ Exemplo: Conformidade com Apple Privacy List
import 'package:flutter/material.dart';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
// Dependências: app_tracking_transparency: ^0.2.0, firebase_analytics: ^10.0.0 (adicione às dependências)
Future<void> requestTrackingPermission() async {
final status = await AppTrackingTransparency.requestTrackingAuthorization();
if (status == TrackingStatus.authorized) {
await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
} else {
await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(false);
}
}
Saída:
Diálogo App Tracking Transparency exibido
Status: authorized (ou denied)
Coleta de analytics habilitada/desabilitada conforme o status
(1) Comparação de Requisitos de Conformidade
| Plataforma | Itens Obrigatórios |
|---|---|
| Google Play | Política de Privacidade / Data Safety Form / Classificação de Conteúdo |
| App Store | Política de Privacidade / ATT / Declaração de Conformidade de Criptografia |
| Web (PWA) | Consentimento de Cookies GDPR / Política de Privacidade |
(2) Checklist de Conformidade de Privacidade
Verificações Pré-release
- [ ] Página de política de privacidade implantada e link acessível
- [ ] Declarações de coleta de dados estão claras (finalidade, período de retenção, compartilhamento com terceiros)
- [ ] Usuários podem solicitar exportação e exclusão de dados
- [ ] Banner de Cookie / popup ATT implementado
- [ ] Proteções especiais para usuários menores de 13 anos (COPPA)
- [ ] Rótulos de tipo de dados da App Store verificados
- [ ] Google Play Data Safety Form enviado
- [ ] Revisão de conformidade GDPR / CCPA aprovada
Checklist de Publicação em Três Plataformas
(1) Android
- [ ] ID do Aplicativo é único
- [ ] Assinatura do keystore verificada
- [ ] Arquivo AAB ≤150MB
- [ ] URL da Política de Privacidade acessível
- [ ] Questionário contentRating completado
- [ ] Target API Level 34
- [ ] Testar AAB no dispositivo via
bundletool - [ ] Upload do AAB para o Play Console
- [ ] Preencher listagem da loja (screenshots, descrição, política de privacidade)
- [ ] Iniciar rollout para 10% → 50% → 100%
(2) iOS
- [ ] Certificado de distribuição válido
- [ ] Provisioning profile corresponde ao Bundle ID
- [ ] Build IPA:
flutter build ipa --release - [ ] Upload IPA via Transporter
- [ ] Preencher listagem no App Store Connect
- [ ] Enviar para revisão (aguardar 24-48 horas)
(3) Web
- [ ] Build:
flutter build web --wasm - [ ] Testar no Chrome/Safari/Firefox
- [ ] Implantar no Firebase Hosting
- [ ] Verificar roteamento de URL funciona
- [ ] Testar prompt de instalação PWA
(4) Pós-release
- [ ] Criar GitHub Release com notas
- [ ] Notificar equipe via Slack
- [ ] Monitorar Crashlytics por 24 horas
- [ ] Monitorar avaliações de usuários
❓ Perguntas Frequentes
P: Qual a diferença entre AAB e APK? R: AAB (Android App Bundle) é o formato de upload — o Google Play gera automaticamente APKs otimizados a partir dele. AABs são menores porque incluem apenas os recursos necessários pelo dispositivo.
P: Quanto tempo leva a revisão da App Store geralmente? R: Primeiras submissões geralmente levam 24-48 horas, atualizações geralmente 12-24 horas. Re-submissões após rejeição exigem outra espera.
P: Como devo gerenciar versionCode e versionName? R: versionCode deve ser um inteiro incremental (+1 para cada release); versionName é visível ao usuário (ex: 1.2.3). Use convenções SemVer.
P: A versão Web precisa de registro ICP? R: Servidores na China continental exigem registro ICP. Servidores no exterior (Firebase/Vercel) não.
P: O que a conformidade GDPR exige? R: 1) Mostrar consentimento de privacidade no primeiro lançamento; 2) Fornecer opção de exclusão de dados; 3) Link da política de privacidade; 4) Minimizar coleta de dados; 5) Usuários podem revogar consentimento.
P: O que devo fazer se a App Store rejeitar minha submissão? R: Leia cuidadosamente o motivo da rejeição, corrija os problemas e reenvie. Motivos comuns: política de privacidade ausente, popup ATT não exibido, crashes, violações de política de conteúdo.
📖 Resumo
(1) Exemplo: Cadência de Release de Número de Versão
1.0.0 → Lançamento MVP (primeiro release)
1.0.1 → Correção urgente de bug (patch)
1.1.0 → Nova funcionalidade (minor)
1.2.3 → Release do ShopApp (minor + patch)
2.0.0 → Refatoração maior (major)
Saída:
SemVer: MAJOR.MINOR.PATCH
- MAJOR mudanças incompatíveis
- MINOR adições compatíveis
- PATCH correções compatíveis
(2) Exemplo: Integração Firebase Crashlytics
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'dart:ui' show PlatformDispatcher;
// Dependências: firebase_core: ^2.0.0, firebase_crashlytics: ^3.0.0 (adicione às dependências)
// ShopApp vem do projeto lib/app.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FlutterError.onError = (details) {
FirebaseCrashlytics.instance.recordFlutterFatalError(details);
};
PlatformDispatcher.instance.onError = (error, stack) {
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
return true;
};
runApp(const ShopApp());
}
Saída:
Crashlytics inicializado
Erros fatais reportados automaticamente
Erros não-fatais reportados automaticamente
(3) Exemplo: Dashboard de Monitoramento de Release
# Firebase Crashlytics
firebase functions:log --only publishMonitor
# Saída esperada:
# {"status":"ok","version":"1.2.3","crashRate":"0.05%"}
Saída:
Taxa de crash após rollout:
- 1h: 0.05% (baseline 0.10%)
- 24h: 0.04% (saudável)
- Taxa ANR: 0.01% (aceitável)
📝 Exercícios
- Básico (dificuldade ⭐): Gere um Android Keystore para o ShopApp, configure a assinatura no build.gradle, e faça build com sucesso de um AAB de release.
- Intermediário (dificuldade ⭐⭐): Complete a preparação de publicação dual-plataforma do ShopApp — assinatura Android AAB + configuração de certificado iOS, e escreva um checklist de publicação multiplataforma.
- Desafio (dificuldade ⭐⭐⭐): Implemente o processo completo de publicação multiplataforma do ShopApp (Android + iOS + Web), incluindo declarações de conformidade de privacidade, geração de screenshots multicanal e escrita de descrição para a App Store.