8 votes

Le téléchargement ne démarre pas sur Android 9 lorsqu'il est demandé à partir d'un WLAN sans internet.

Je travaille sur une application Android qui se connecte à un serveur Flask local en utilisant le WiFi. Ensuite, l'application affiche des images qui sont stockées sur le serveur (RPi3). Un clic sur une image déclenche une demande de téléchargement et je veux que le DownloadManager Android mette en file d'attente la demande et télécharge l'image. Le réseau WiFi ne fournit pas d'accès à Internet.

Jusqu'à présent, j'ai pu le tester sur des appareils Android 6 et Android 8.1 et tout fonctionne bien. En testant sur plusieurs appareils Android 9, le téléchargement ne démarre pas, mais après s'être déconnecté du réseau local, les tentatives échouées sont affichées.

En lisant d'autres fils de discussion à ce sujet, j'ai essayé ce qui suit :

Et ajouté dans le AndroidManifest.xml :

android:networkSecurityConfig="@xml/network_security_config"
  • Lier le réseau comme décrit dans la première réponse ici : Utilisation d'un WiFi sans connexion Internet

  • Jouer avec la les options offertes par la classe DownloadManager.Request mais elles ne semblent pas liées à ce problème :

    .setRequiresCharging(false) .setAllowedOverMetered(false) .setAllowedOverRoaming(false) .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, (String) url);

  • Nouvelle vérification autorisations . Ils sont activés :

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />

Il s'agit de la demande de téléchargement Je crée :

DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url))
        .setTitle("Some Title")
        .setDescription("Downloading a file")
        .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
        .setDestinationInExternalPublicDir("some_path", (String) url)
        .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
DownloadManager downloadManager= (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
downloadID = downloadManager.enqueue(request);

Le Serveur Flask (Python3) l'utilise pour renvoyer l'image :

    @app.route('/getFullImage/<image_file>')
    def get_full_image(image_file):
        log.debug("Client requests full image.")
        folder = os.path.join(app.root_path, "media_images")

        return flask.send_from_directory(directory=folder, filename=image_file, as_attachment=True)

Comme indiqué, sur Android 6 et 8.1, cela a fonctionné correctement, mais aucun des appareils Android 9 ne démarre le téléchargement. S'il existe un paramètre ou une méthode que je ne connais pas, je serais heureux de l'apprendre.

Nous vous remercions.

2voto

La clé de ce problème est de lier le processus au réseau. Cela permet à votre application d'utiliser le wifi même si le wifi n'a pas de connectivité internet.

Voici mon code, il est en kotlin mais vous pouvez aussi le convertir en Java

Il suffit de l'appeler n'importe où avant d'essayer de faire une demande. Pour ma part, je l'ai placé dans l'initialisation d'une classe singleton que j'utilise comme utilitaire réseau.

fun bindProcessToNetwork() {
    // Unbind the process from the network
    getConnectivityManager().bindProcessToNetwork(null)

    // Bind the process to the network
    getConnectivityManager().bindProcessToNetwork(getWifiNetwork())
}

Voici les autres méthodes que j'ai utilisées dans bindProcessToNetwork. Vous remarquerez que j'ai utilisé une boucle for pour itérer à travers tous les réseaux et essayer de déterminer lequel est wifi au lieu d'utiliser connectionManager.activeNetworkInfo parce qu'il renvoie au réseau cellulaire lorsque le wifi n'a pas de connectivité internet.

private fun getConnectivityManager() : ConnectivityManager {
    val context = ApplicationContextProvider.getContext()
    return context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
}

private fun getWifiNetwork(): Network? {
    val networks = getConnectivityManager().allNetworks
    for (network in networks) {
        if (isNetworkWifi(network)) {
            return network
        }
    }
    return null
}

private fun isNetworkWifi(network: Network): Boolean {
    return this.getConnectivityManager().getNetworkCapabilities(network)
        .hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
}

Vous pouvez consulter la documentation de WifiManager y Gestionnaire de connectivité pour plus d'informations. Beaucoup de choses ont été supprimées au niveau 28 (Android 9). Assurez-vous de n'utiliser ce code que sous Android 9 ou supérieur.

if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P){
    bindProcessToNetwork(); 
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X