Revision previa al envio a produccion. Cada punto se verifico en el codigo antes de tocarlo; lo que ya estaba bien se dejo como estaba. Ubicacion: se declaraba precision fina sin usarla El unico consumidor de ubicacion pide `LocationAccuracy.low` y se queda solo con el codigo ISO del pais, asi que `ACCESS_FINE_LOCATION` no aportaba nada. Y contradecia la declaracion de Seguridad de los datos ya aprobada en Play, que dice ubicacion APROXIMADA: declarar una cosa y pedir otra es precisamente lo que se penaliza en revision. Verificado que los manifiestos de geolocator_android y geocoding_android no declaran permisos propios, asi que el merge no lo reinyecta y no hace falta `tools:node="remove"`. El plugin construye su peticion en tiempo de ejecucion a partir de lo declarado, de modo que con COARSE pide COARSE. Sin cambio funcional: la deteccion de pais sigue igual. El paywall vendia Android Auto como exclusivo, y ya no lo es La etiqueta era literalmente "Android Auto", a secas. Pero el tier gratuito recibio una carpeta navegable con emisoras reproducibles cuando hubo que cumplir las guias del coche, asi que esa frase dejo de ser cierta. Ahora dice que PRO añade el catalogo completo, favoritos, mis emisoras y musica local, y aclara que gratis tiene las destacadas. Un paywall que promete lo que el tier gratuito ya tiene expone a reclamacion y a que se cite en revision. Microfono: se pide al activar el visualizador, no antes Con una explicacion previa en los 13 idiomas, en vez de aparecer sin contexto. Grabacion: uso privado de verdad, no solo en el aviso La pantalla de grabaciones entregaba el fichero a cualquier aplicacion con `Share.shareXFiles`. La intencion era abrirlo en un reproductor del propio telefono, no redistribuirlo, y una cosa es copia privada y la otra no. Ahora usa el `openFile` que ya existia -- FileProvider + ACTION_VIEW -- y avisa cuando ningun reproductor del dispositivo puede abrirla, en vez de fallar en silencio. Se añade ademas el aviso de uso privado en esa pantalla. `recordingActionShare` la usaban DOS botones con significados distintos: el de grabaciones, que mandaba el audio, y el del reproductor, que comparte el nombre y la url de la emisora. Una clave, dos sentidos, y esa ambiguedad basto para que al leer el codigo pareciera que solo se compartian enlaces. Separadas en `stationActionShare` y `recordingActionOpenIn`. La grabacion sigue siendo PRO. Lo que reduce el riesgo es que la copia no salga del dispositivo, no regalar la funcion: los anuncios tambien son monetizacion. Suite completa: 1587 pasan, 2 omitidos. flutter analyze mantiene los 5 avisos preexistentes.
164 lines
7.7 KiB
XML
164 lines
7.7 KiB
XML
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
<!-- Permisos requeridos para streaming de audio -->
|
|
<uses-permission android:name="android.permission.INTERNET"/>
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
|
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED"/>
|
|
<uses-permission android:name="android.permission.WAKE_LOCK"/>
|
|
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
|
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
|
|
<uses-permission android:name="android.permission.USE_EXACT_ALARM"/>
|
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
|
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT"/>
|
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
|
<!-- Approximate location ONLY. The single consumer
|
|
(EstadoBusqueda.cargarEmisorasCercanas) asks for LocationAccuracy.low
|
|
and throws the fix away except for Placemark.isoCountryCode, so a
|
|
country-level fix is all this app can use. Declaring
|
|
ACCESS_FINE_LOCATION would also contradict the approved Data Safety
|
|
declaration. geolocator builds its runtime request from whichever of
|
|
the two permissions the merged manifest declares, so with COARSE
|
|
alone the system dialog offers approximate precision only. -->
|
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
|
|
<!--
|
|
Reading the paired-device list is gated by BLUETOOTH_CONNECT from API 31
|
|
and by this legacy permission below it. Normal permission: granted at
|
|
install, no runtime prompt.
|
|
-->
|
|
<uses-permission
|
|
android:name="android.permission.BLUETOOTH"
|
|
android:maxSdkVersion="30"/>
|
|
|
|
<application
|
|
android:label="PluriWave"
|
|
android:name="${applicationName}"
|
|
android:icon="@mipmap/ic_launcher"
|
|
android:roundIcon="@mipmap/ic_launcher_round"
|
|
android:networkSecurityConfig="@xml/network_security_config">
|
|
<activity
|
|
android:name=".MainActivity"
|
|
android:exported="true"
|
|
android:launchMode="singleTop"
|
|
android:taskAffinity=""
|
|
android:theme="@style/LaunchTheme"
|
|
android:showWhenLocked="true"
|
|
android:turnScreenOn="true"
|
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
|
android:hardwareAccelerated="true"
|
|
android:windowSoftInputMode="adjustResize">
|
|
<meta-data
|
|
android:name="io.flutter.embedding.android.NormalTheme"
|
|
android:resource="@style/NormalTheme"
|
|
/>
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MAIN"/>
|
|
<category android:name="android.intent.category.LAUNCHER"/>
|
|
</intent-filter>
|
|
</activity>
|
|
|
|
<!-- Servicio de audio en background (audio_service) -->
|
|
<service
|
|
android:name="com.ryanheise.audioservice.AudioService"
|
|
android:foregroundServiceType="mediaPlayback"
|
|
android:exported="true">
|
|
<intent-filter>
|
|
<action android:name="android.media.browse.MediaBrowserService"/>
|
|
</intent-filter>
|
|
</service>
|
|
|
|
<service
|
|
android:name=".PluriWaveAlarmService"
|
|
android:foregroundServiceType="mediaPlayback|systemExempted"
|
|
android:exported="false" />
|
|
|
|
<!-- Receptor de controles de media (auriculares, notificación) -->
|
|
<receiver
|
|
android:name="com.ryanheise.audioservice.MediaButtonReceiver"
|
|
android:exported="true">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.MEDIA_BUTTON"/>
|
|
</intent-filter>
|
|
</receiver>
|
|
|
|
<receiver
|
|
android:name=".PluriWaveAlarmReceiver"
|
|
android:exported="false"
|
|
android:directBootAware="true">
|
|
<intent-filter>
|
|
<action android:name="es.freetimelab.pluriwave.alarm.FIRE"/>
|
|
<action android:name="es.freetimelab.pluriwave.alarm.PRE_NOTICE"/>
|
|
<action android:name="es.freetimelab.pluriwave.alarm.SKIP_NEXT"/>
|
|
<action android:name="es.freetimelab.pluriwave.alarm.POSTPONE_NEXT"/>
|
|
</intent-filter>
|
|
</receiver>
|
|
|
|
<receiver
|
|
android:name=".PluriWaveBootReceiver"
|
|
android:exported="true"
|
|
android:directBootAware="true">
|
|
<intent-filter>
|
|
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/>
|
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
|
<action android:name="android.intent.action.USER_UNLOCKED"/>
|
|
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
|
|
<action android:name="android.intent.action.TIME_SET"/>
|
|
<action android:name="android.intent.action.TIMEZONE_CHANGED"/>
|
|
<action android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED"/>
|
|
</intent-filter>
|
|
</receiver>
|
|
|
|
<provider
|
|
android:name="androidx.core.content.FileProvider"
|
|
android:authorities="${applicationId}.fileprovider"
|
|
android:exported="false"
|
|
android:grantUriPermissions="true">
|
|
<meta-data
|
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
android:resource="@xml/pluriwave_file_paths" />
|
|
</provider>
|
|
|
|
<!--
|
|
Publishes the app-private recordings folder as a browsable storage
|
|
root for the system file manager. MANAGE_DOCUMENTS restricts direct
|
|
access to the document framework (DocumentsUI); grantUriPermissions
|
|
lets it hand single-file access to whatever app the user picks.
|
|
-->
|
|
<provider
|
|
android:name=".RecordingsDocumentsProvider"
|
|
android:authorities="${applicationId}.recordings"
|
|
android:exported="true"
|
|
android:grantUriPermissions="true"
|
|
android:permission="android.permission.MANAGE_DOCUMENTS">
|
|
<intent-filter>
|
|
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
|
|
</intent-filter>
|
|
</provider>
|
|
|
|
<meta-data
|
|
android:name="flutterEmbedding"
|
|
android:value="2" />
|
|
|
|
<!-- Android Auto discovery (android-auto-media) -->
|
|
<meta-data
|
|
android:name="com.google.android.gms.car.application"
|
|
android:resource="@xml/automotive_app_desc" />
|
|
|
|
<!-- AdMob application id (iap-freemium-unlock). Real id, provisioned
|
|
in the AdMob console. Safe to use in all build modes — this id
|
|
only initializes the SDK; it never serves an ad by itself, so it
|
|
carries none of the "don't tap your own ads" risk that ad unit
|
|
ids do. -->
|
|
<meta-data
|
|
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
|
android:value="ca-app-pub-6038935671414339~4085536467" />
|
|
</application>
|
|
<queries>
|
|
<intent>
|
|
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
|
<data android:mimeType="text/plain"/>
|
|
</intent>
|
|
</queries>
|
|
</manifest>
|