80 votes

Android - Comment télécharger un fichier à partir d'un serveur Web ?

Dans mon application, je télécharge un kml à partir d'un serveur web. J'ai défini les autorisations pour le stockage externe et l'Internet dans mon fichier manifeste Android. Je suis nouveau dans le monde d'Android, votre aide est très appréciée.

MainActivity.java

package com.example.demo;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        DownloadFiles();
    }

    public void DownloadFiles(){
        try {
            URL u = new URL("http://www.qwikisoft.com/demo/ashade/20001.kml");
            InputStream is = u.openStream();
            DataInputStream dis = new DataInputStream(is);

            byte[] buffer = new byte[1024];
            int length;

            FileOutputStream fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/" + "data/test.kml"));
            while ((length = dis.read(buffer)) > 0) {
                fos.write(buffer, 0, length);
            }

        } catch (MalformedURLException mue) {
            Log.e("SYNC getUpdate", "malformed url error", mue);
        } catch (IOException ioe) {
            Log.e("SYNC getUpdate", "io error", ioe);
        } catch (SecurityException se) {
            Log.e("SYNC getUpdate", "security error", se);
        }
    }
}

Fichier manifeste Android

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.demo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity
            android:name="com.example.demo.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Erreur de logcat :

FATAL EXCEPTION : main java.lang.RuntimeException : Impossible de démarrer l'activité ComponentInfo{com.example.demo/com.example.demo.MainActivity} : Android.os.NetworkOnMainThreadException at Android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956) at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981) at Android.app.ActivityThread.access$600(ActivityThread.java:123) at Android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147) at Android.os.Handler.dispatchMessage(Handler.java:99) at Android.os.Looper.loop(Looper.java:137) at Android.app.ActivityThread.main(ActivityThread.java:4424) at java.lang.reflect.Method.invokeNative(Méthode native) at java.lang.reflect.Method.invoke(Method.java:511) at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) at com.Android.internal.os.ZygoteInit.main(ZygoteInit.java:551) at dalvik.system.NativeStart.main(Méthode native) Causé par : Android.os.NetworkOnMainThreadException at Android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099) at java.net.InetAddress.lookupHostByName(InetAddress.java:391) at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242) at java.net.InetAddress.getAllByName(InetAddress.java:220) at libcore.net.http.HttpConnection.(HttpConnection.java:71) at libcore.net.http.HttpConnection.(HttpConnection.java:50) at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:351) at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:86) at libcore.net.http.HttpConnection.connect(HttpConnection.java:128) at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:308) at libcore.net.http.HttpEngine.connect(HttpEngine.java:303) at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282) at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232) at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:273) at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:168) at java.net.URL.openStream(URL.java:462) at com.example.demo.MainActivity.DownloadFiles(MainActivity.java:30) at com.example.demo.MainActivity.onCreate(MainActivity.java:24) at Android.app.Activity.performCreate(Activity.java:4465) at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049) at Android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)

EDITAR

package com.example.demo;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

public class MainActivity extends Activity {

    private ProgressDialog pDialog;
    public static final int progress_bar_type = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        new DownloadFileFromURL().execute("http://www.qwikisoft.com/demo/ashade/20001.kml");
    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case progress_bar_type: // we set this to 0
                pDialog = new ProgressDialog(this);
                pDialog.setMessage("Downloading file. Please wait...");
                pDialog.setIndeterminate(false);
                pDialog.setMax(100);
                pDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                pDialog.setCancelable(true);
                pDialog.show();
                return pDialog;
            default:
                return null;
        }
    }

    class DownloadFileFromURL extends AsyncTask<String, String, String> {

        /**
         * Before starting background thread Show Progress Bar Dialog
         **/
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showDialog(progress_bar_type);
        }

        /**
         * Downloading file in background thread
         **/
        @Override
        protected String doInBackground(String... f_url) {
            int count;
            try {
                URL url = new URL(f_url[0]);
                URLConnection conection = url.openConnection();
                conection.connect();

                // this will be useful so that you can show a tipical 0-100%
                // progress bar
                int lenghtOfFile = conection.getContentLength();

                // download the file
                InputStream input = new BufferedInputStream(url.openStream(),
                        8192);

                // Output stream
                OutputStream output = new FileOutputStream(Environment
                        .getExternalStorageDirectory().toString()
                        + "/data/downloadedfile.kml");

                byte data[] = new byte[1024];

                long total = 0;

                while ((count = input.read(data)) != -1) {
                    total += count;
                    // publishing the progress....
                    // After this onProgressUpdate will be called
                    publishProgress("" + (int) ((total * 100) / lenghtOfFile));

                    // writing data to file
                    output.write(data, 0, count);
                }

                // flushing output
                output.flush();

                // closing streams
                output.close();
                input.close();
            } catch (Exception e) {
                Log.e("Error: ", e.getMessage());
            }

            return null;
        }

        /**
         * Updating progress bar
         **/
        protected void onProgressUpdate(String... progress) {
            // setting progress percentage
            pDialog.setProgress(Integer.parseInt(progress[0]));
        }

        /**
         * After completing background task Dismiss the progress dialog
         **/
        @Override
        protected void onPostExecute(String file_url) {
            // dismiss the dialog after the file was downloaded
            dismissDialog(progress_bar_type);
        }
    }
}

Lorsque j'exécute ce code dans l'émulateur, le code ne fonctionne toujours pas - le fichier n'est pas téléchargé.

6voto

Mathan Chinna Points 287

M. Iam4fun votre réponse de code ici ... Vous utiliserez le fil...

   findViewById(R.id.download).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            new Thread(new Runnable() {
                public void run() {
                    DownloadFiles();
                }
            }).start();

Et, alors..

 public void DownloadFiles(){

        try {
            URL u = new URL("http://www.qwikisoft.com/demo/ashade/20001.kml");
            InputStream is = u.openStream();

            DataInputStream dis = new DataInputStream(is);

            byte[] buffer = new byte[1024];
            int length;

            FileOutputStream fos = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/" + "data/test.kml"));
            while ((length = dis.read(buffer))>0) {
              fos.write(buffer, 0, length);
            }

          } catch (MalformedURLException mue) {
            Log.e("SYNC getUpdate", "malformed url error", mue);
          } catch (IOException ioe) {
            Log.e("SYNC getUpdate", "io error", ioe);
          } catch (SecurityException se) {
            Log.e("SYNC getUpdate", "security error", se);
          }
}
}

0voto

AZone Points 2153

Utiliser AsyncTask et

mettez le code de votre fichier de téléchargement dans doinbackground d'elle..

Android ne permet plus d'effectuer des tâches lourdes sur le thread principal pour éviter l'erreur ANR (Application not responding).

0voto

sabadow Points 2439

Vous devez utiliser une AsyncTask (ou un autre moyen d'effectuer une opération réseau en arrière-plan).

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //create and execute the download task
    MyAsyncTask async = new MyAsyncTask();
    async.execute();

}

private class MyAsyncTask extends AsyncTask<Void, Void, Void>{

    //execute on background (out of the UI thread)
    protected Long doInBackground(URL... urls) {
        DownloadFiles();
    }

}

Plus d'informations sur AsyncTask sur Documentation Android

J'espère que cela vous aidera.

0voto

TeeTracker Points 692

Exécutez ces codes dans un thread ou une AsyncTask. Afin d'éviter les appels répétés de la même _url (une fois pour getContentLength(), une fois pour openStream()), utilisez IOUtils.toByteArray de Apache.

void downloadFile(String _url, String _name) {
    try {
        URL u = new URL(_url);
        DataInputStream stream = new DataInputStream(u.openStream());
        byte[] buffer = IOUtils.toByteArray(stream);
        FileOutputStream fos = mContext.openFileOutput(_name, Context.MODE_PRIVATE);
        fos.write(buffer);
        fos.flush();
        fos.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        return;
    } catch (IOException e) {
        e.printStackTrace();
        return;
    }
}

0voto

user6823720 Points 1

En plus d'utiliser AsyncTask, vous pouvez placer l'opération dans runnable-

Runnable r=new Runnable()
{

public void run()
{
///-------network operation code
}
};

//--------call r in this way--
Thread t=new Thread(r);`enter code here`
t.start();

Also put the UI work in a handler..such as updating a textview etc..

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