Android – 如何从networking服务器下载文件

在我的应用程序,我正在从web服务器下载kml文件。我已经设置了外部存储和互联网在我的Android清单文件的权限。我是新来的android,你的帮助是极大的赞赏

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); } } } 

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> 

Logcat错误:

 FATAL EXCEPTION: main java.lang.RuntimeException: Unable to start activity 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(Native Method) 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(Native Method) Caused by: 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.<init>(HttpConnection.java:71) at libcore.net.http.HttpConnection.<init>(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) 

编辑

 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); } } } 

当我在模拟器中运行此代码的代码仍然无法正常工作..文件不下载。

Solutions Collecting From Web of "Android – 如何从networking服务器下载文件"

使用asynchronous任务 。 (如果不工作在4.0然后添加

 StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); 

当你想下载文件时调用: new DownloadFileFromURL().execute(file_url);

 public class MainActivity extends Activity { // Progress Dialog private ProgressDialog pDialog; public static final int progress_bar_type = 0; // File url to download private static String file_url = "http://www.qwikisoft.com/demo/ashade/20001.kml"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new DownloadFileFromURL().execute(file_url); } /** * Showing Dialog * */ @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; } } /** * Background Async Task to download file * */ 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() + "/2011.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); } } } 

在主线程上执行networking操作是不好的做法,这就是为什么你看到NetworkOnMainThreadException 。 这是由政策阻止。 如果您确实需要进行testing,请在OnCreate中添加以下内容:

  StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); 

请记住,这是非常不好的做法,并应理想地将您的networking代码移动到AsyncTaskThread

在线程或AsyncTask中运行这些代码。 为了避免同一个_url(一次为getContentLength(),一次openStream())重复调用,使用Apache的IOUtils.toByteArray。

 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; } } 

除了使用AsyncTask,你可以把操作放在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 haldler..such as updating a textview etc.. 

Mr.Iam4fun你的代码在这里回答..你会使用线程…

  findViewById(R.id.download).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { public void run() { DownloadFiles(); } }).start(); 

接着..

  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); } } } 

当然,这将工作..

从api级别11或者Honeycomb开始,在主线程上进行networking操作是被禁止的。 使用线程或asynctask。 欲了解更多信息,请访问https://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

使用AsyncTask

把你的下载文件代码放在它的doinbackground中..

android不允许在主线程上执行繁重的任务来避免ANR(应用程序不响应)错误

您应该使用AsyncTask(或其他方式在后台执行networking操作)。

 @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(); } } 

有关Android文档上的 AsyncTask的更多信息

希望能帮助到你。