Java和Android Http連接程序:使用java.net.URL 下載服務器圖片到客戶端
本博客前面博文中利用org.apache.http包中API進行Android客戶端HTTP連接的例子:
Android HTTP實例 使用GET方法和POST方法發送請求
另一種常用的建立Http連接的常用方式是利用Java在JDK中提供的類,也即本文要演示的方法,本文的例子程序實現的功能是從服務器上下載圖片到客戶端。
關於兩種建立Http連接方法(apache的包和JDK的包)的討論可以看看后面的參考鏈接。
服務器端
服務器端需要准備圖片,因為是Demo程序,所以我就准備了一張圖片,然后把它放在Web Project的WebRoot路徑下:
然后只要啟動Tomcat,ipconfig查出ip地址,放在之后要用的路徑中就可以了。
Java程序:Http連接 獲取並下載服務器端圖片
寫一個工具類:
其中第一個方法根據給出的服務器地址及資源路徑得到輸入流:
public static InputStream getInputStream(String path) { InputStream inputStream = null; HttpURLConnection httpURLConnection = null; try { URL url = new URL(path); if (null != url) { httpURLConnection = (HttpURLConnection) url.openConnection(); // 設置連接網絡的超時時間 httpURLConnection.setConnectTimeout(5000); // 打開輸入流 httpURLConnection.setDoInput(true); // 設置本次Http請求使用的方法 httpURLConnection.setRequestMethod("GET"); if (200 == httpURLConnection.getResponseCode()) { // 從服務器獲得一個輸入流 inputStream = httpURLConnection.getInputStream(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return inputStream; }
第二個方法根據輸入流將文件存儲在本地一個路徑:
public static void saveInputStream(InputStream inputStream, String saveToPath) { byte[] data = new byte[1024]; int len = 0; FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(saveToPath); while (-1 != (len = inputStream.read(data))) { fileOutputStream.write(data, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != fileOutputStream) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
完整代碼:

package com.meng.utils; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class HttpUtils { public static InputStream getInputStream(String path) { InputStream inputStream = null; HttpURLConnection httpURLConnection = null; try { URL url = new URL(path); if (null != url) { httpURLConnection = (HttpURLConnection) url.openConnection(); // 設置連接網絡的超時時間 httpURLConnection.setConnectTimeout(5000); // 打開輸入流 httpURLConnection.setDoInput(true); // 設置本次Http請求使用的方法 httpURLConnection.setRequestMethod("GET"); if (200 == httpURLConnection.getResponseCode()) { // 從服務器獲得一個輸入流 inputStream = httpURLConnection.getInputStream(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return inputStream; } public static void saveInputStream(InputStream inputStream, String saveToPath) { byte[] data = new byte[1024]; int len = 0; FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(saveToPath); while (-1 != (len = inputStream.read(data))) { fileOutputStream.write(data, 0, len); } } catch (IOException e) { e.printStackTrace(); } finally { if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != fileOutputStream) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
測試程序:
package com.meng.learn; import java.io.InputStream; import com.meng.utils.HttpUtils; public class HttpTest { private static String URL_PATH = "http://192.168.11.6:8080/HelloWeb/android.jpg"; public static void main(String[] args) { InputStream inputStream = HttpUtils.getInputStream(URL_PATH); HttpUtils.saveInputStream(inputStream,"D:\\test1.jpg"); } }
程序運行成功之后可以在指定路徑下發現多了服務器端的那個圖片。
Android客戶端 Http連接:下載服務器端的圖片到SD卡
Android的程序還需要考慮的幾點是:
1.對SD卡的訪問權限及操作。
2.為了不阻塞UI線程,下載操作放在獨立的線程中。
3.加入了網路訪問的檢查,確認網絡連接后再進行下載。
需要添加的權限
<!-- 往SDCard寫入數據權限 --> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 聯網權限 --> <uses-permission android:name="android.permission.INTERNET" /> <!-- 獲取網絡狀態的權限 --> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
布局文件如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:padding="10dp" android:id="@+id/info" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="14sp" /> <Button android:id="@+id/btn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Download Image" android:textSize="14sp" /> <ImageView android:padding="10dp" android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Activity中所做的就是按下按鈕之后,連接服務器,將圖片取出顯示在ImageView里,同時存往SD卡的指定路徑:
package com.mengexample.test; import java.io.InputStream; import com.windexample.utils.FileUtils; import com.windexample.utils.HttpUtils; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.AsyncTask; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; public class ImageDownloadActivity extends Activity { private static String URL_PATH = "http://192.168.11.6:8080/HelloWeb/android.jpg"; private TextView mTextView = null; private Button mButton = null; private ImageView mImageView = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_image_download); mTextView = (TextView) findViewById(R.id.info); mTextView.setText(URL_PATH); mButton = (Button) findViewById(R.id.btn); mButton.setOnClickListener(mBtnClickListener); mImageView = (ImageView) findViewById(R.id.image); } private OnClickListener mBtnClickListener = new OnClickListener() { @Override public void onClick(View v) { // 首先確認網絡連接 ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = connectivityManager .getActiveNetworkInfo(); if (null != networkInfo && networkInfo.isConnected()) { new DownloadImageTask().execute(URL_PATH); } else { Toast.makeText(ImageDownloadActivity.this, "No network connection available", Toast.LENGTH_SHORT) .show(); } } }; private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { @Override protected Bitmap doInBackground(String... params) { String path = params[0]; InputStream inputStream = HttpUtils.getInputStream(path); // 從輸入流得到位圖 Bitmap bitmap = BitmapFactory.decodeStream(inputStream); // 將圖像存儲到SD卡 FileUtils.saveToSDCard(bitmap, "TestImage", "android.jpg"); return bitmap; } @Override protected void onPostExecute(Bitmap result) { // 將圖像顯示出來 mImageView.setImageBitmap(result); } } }
其中用到的兩個工具類:
建立連接並獲取輸入流的方法和Java代碼中的一樣:
package com.windexample.utils; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class HttpUtils { public static InputStream getInputStream(String path) { InputStream inputStream = null; HttpURLConnection httpURLConnection = null; try { URL url = new URL(path); if (null != url) { httpURLConnection = (HttpURLConnection) url.openConnection(); // 設置連接網絡的超時時間 httpURLConnection.setConnectTimeout(5000); // 打開輸入流 httpURLConnection.setDoInput(true); // 設置本次Http請求使用的方法 httpURLConnection.setRequestMethod("GET"); if (200 == httpURLConnection.getResponseCode()) { // 從服務器獲得一個輸入流 inputStream = httpURLConnection.getInputStream(); } } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return inputStream; } }
另一個輔助類提供了方法,將位圖存入SD卡的指定路徑:
package com.windexample.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import android.graphics.Bitmap; import android.os.Environment; import android.util.Log; public class FileUtils { private static String TAG = "File"; public static String getSDCardRootPath() { // SD卡根目錄 String sDCardRoot = Environment.getExternalStorageDirectory() .getAbsolutePath(); return sDCardRoot; } public static void saveToSDCard(Bitmap bitmap, String filePath, String fileName) { // 將所給文件路徑和文件名與SD卡路徑連接起來 String sdcardRoot = getSDCardRootPath(); // 創建文件路徑 File dir = new File(sdcardRoot + File.separator + filePath); Log.i(TAG, "dir: " + dir); if (!dir.exists()) { dir.mkdirs(); } File targetFile = new File(dir, fileName); try { targetFile.createNewFile(); FileOutputStream fileOutputStream = new FileOutputStream(targetFile); bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
程序運行后並得到圖片后,結果如下:
並且查看SD卡下的TestImage路徑,發現其中有這個圖片文件。
參考資料
Android Training: Connecting to the Network:
http://developer.android.com/training/basics/network-ops/connecting.html
Android Training: Processes and Threads
http://developer.android.com/guide/components/processes-and-threads.html
老羅Android開發視頻教程。
Android之網絡編程 系列博文:
http://www.cnblogs.com/devinzhang/category/349642.html
本博客前面博文中利用org.apache.http包中API進行Android客戶端HTTP連接的例子:
Android HTTP實例 使用GET方法和POST方法發送請求