android的 網絡下載和數據持久化

前三篇 講了listViewhandler,嘿嘿 這次再說一個 URL類 和 androidio,下一此就將這幾個內容 融合一下,做一個從服務器下載較大文件的小實例,怎麼樣期待吧 O(_)O哈哈~

先給大家 介紹一個可以模擬服務器的小工具,hfs

一個小服務器,用tomcat也一樣,不過這個很小,只有800kb而已。做個測試夠用了,我會附加在博客後面的。

這個服務器沒啥好說的,唯一要注意的就是在項目中訪問服務器路徑的時候 要寫http://10.0.2.2:8080/path   有端口就寫端口號沒有就不用寫了,目錄別有中文和特殊符號就好,如果非得有,就涉及到瀏覽器的一些編碼問題了。

ok 現在說說怎麼使用URL類吧。。。

第一步:使用網絡資源的話 需要在清單文件中註冊權限:


這是文本編輯模式,看代碼的就是 加這樣一句話

<uses-permission android:name="android.permission.INTERNET"/>

給大家看看不加權限的後果撒。。。

項目 沒有報fc,但是在日誌裏面會打出這樣的日誌:

日誌的第一句就寫出 permission denied 的錯誤信息,這就是說 沒有註冊權限撒。。。


第二步:代碼篇:


import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnClickListener// 額注意這裏的點擊事件是android.view.View.OnClickListener包下的
{
    // 瀏覽器中的URL:http://localhost:8080/downloading/
    // 項目中要報localhost改爲10.0.2.2
    private final static String URL_PATH = "http://10.0.2.2:8080/test";
    private final static String TEXT_PATH = "/text.txt";
    private final static String IMAGE_PATH = "/img.png";
    private final static String LOCALHOST_TXT_PATH = "/test.txt";//下面的項目用的。。。
    private URL url;
    private URLConnection urlConn;
    private ImageView mImageView;
    private TextView mTextView;
    private TextView mLocalhost;//io代碼所用
    private EditText mWrite;//io代碼所用
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.b_load_img).setOnClickListener(this);
        findViewById(R.id.b_load_text).setOnClickListener(this);
        findViewById(R.id.b_load_localhost).setOnClickListener(this);
        findViewById(R.id.b_write).setOnClickListener(this);
        mWrite = (EditText) findViewById(R.id.et_write);
        mTextView = (TextView) findViewById(R.id.tv_show_text);
        mImageView = (ImageView) findViewById(R.id.img_show_loadimg);
        mLocalhost = (TextView) findViewById(R.id.tv_localhost);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    @Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
        case R.id.b_load_text:
            loadText();// 加載文本
            break;
        case R.id.b_load_img:
            loadImg();// 加載圖片
            break;
        default:
            break;
        }
    }
    private void loadText()// 加載文本
    {
        InputStream is = null;// 爲了關閉流文件java知識,不多解釋了。。。
        try
        {
            url = new URL(URL_PATH + TEXT_PATH);// 獲取URL資源 拋出
                                                // MalformedURLException
            urlConn = url.openConnection();// 獲得連接 拋出 IOException
            // 獲得連接後 就可以得到從服務器傳來的一個IO流
            is = urlConn.getInputStream();
            // input的流都有了 那些就 解析它咯;
            StringBuilder strbuff = new StringBuilder();// 有人會問這裏爲什麼不用StringBuffer
                                                        // ,看源代碼就知道了buffer是線程安全的,
                                                        // 在這裏完全沒必要,浪費資源
            byte[] buffer = new byte[1024];// 定義一個字節緩衝數組
            int len = 0; // len 用來接收從is中讀取到的字節數,
            // 有人會說 這個完全沒用麼,嘿嘿,如果有經驗的就會知道,buffer不一定會被完全充滿,
            // 沒充滿後面剩餘的部分按照java語法就全部賦值爲0了,那麼當你打印出讀取內容時就會發現一堆的亂碼
            // 不相信的 話可是試試 把len去掉撒~,編程麼 就是在各種實驗中成長的撒~
            while (-1 != (len = is.read(buffer)))
            {
                strbuff.append(new String(buffer, 0, len));
            }
            mTextView.setText(strbuff.toString());
        }
        catch (MalformedURLException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if(is != null){
                    is.close();
                }
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    private void loadImg()// 加載圖片
    {//相比於解析文本 解析圖片就要輕鬆多了,android系統提供了一個Bitmap類和BitmapFactory來解析這傢伙
     //看代碼:
        try
        {
            url = new URL(URL_PATH+IMAGE_PATH);
            urlConn = url.openConnection();
            InputStream is = urlConn.getInputStream();//到這裏步驟跟加載文本都一樣撒。。
            //開始加載圖片
            Bitmap map = BitmapFactory.decodeStream(is);//額(⊙o⊙)… 圖片加載ok了
            //不信 就把這傢伙放到 UI中試試。。。
            mImageView.setImageBitmap(map);
            //不知道大家以前有沒有學過 怎麼設置 ImageView 顯示的圖片。。。
            //這裏多說句吧。。。
            //如果有資源id 的話 可以直接這樣設置的mImageView.setImageResource(R.drawable.ic_launcher);
            //android系統有很多設置圖片的方式setImageBitmap();只是其中一種而已。。。
        }
        catch (MalformedURLException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

嘿嘿 不知道 ,大家記不記得 我第三篇博客有說過,向這樣的下載資源是屬於 耗時操作的。必須要在子線程中執行滴。。。嘿嘿先不急 先讓大夥兒體驗下 ANR的魅力。

有興趣的話 大家可以自己試試 看能不能解決這個ANR

第二話題:訪問本地資源

Android4中訪問本地資源的方式先說說其中一種,訪問sdCard有很多人寫sdCardpath 時 喜歡直接寫/mnt/sdcard這是不規範的寫法。如果你的項目是定製的話,這樣就很可能訪問不到本地的sdcard了,正確的寫法應該是這樣滴:

File sdCardFile = Environment.getExternalStorageDirectory();//這個方式獲得的file就是sdCard的路徑

看看代碼吧:

第一步:訪問本地資源 同樣需要 用戶權限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

第二步:寫代碼咯


private void write()
    {// 寫入本地文件 : 需要權限:<uses-permission
     // android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        File sdCardFile = Environment.getExternalStorageDirectory();// 得到的是sdcard的目錄路徑
        String path = sdCardFile.getAbsolutePath() + LOCALHOST_TXT_PATH;// 構建完整路徑
        FileOutputStream fos = null;
        try
        {
            String str = mWrite.getText().toString();//從組件中得到輸入的值
            fos = new FileOutputStream(path);
            fos.write(str.getBytes());//寫入文本
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (fos != null)
                    fos.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    }
    private void localhost()
    {// 讀取本地文件 . 需要權限:<uses-permission
     // android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        //其實這個方法 跟 從網絡獲取資源差不多。。。 只是信息來源不同而已撒~~~
        File sdCardFile = Environment.getExternalStorageDirectory();// 得到的是sdcard的目錄路徑
        String path = sdCardFile.getAbsolutePath() + LOCALHOST_TXT_PATH;// 構建完整路徑
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream(path);
            StringBuilder strBuff = new StringBuilder();
            byte[] buffer = new byte[1024];
            int len = 0;
            while(-1 != (len = fis.read(buffer))){
                strBuff.append(new String (buffer,0,len));
            }
            mLocalhost.setText(strBuff.toString());
        }
        catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
                                                                                                
                                                                                            
    }


這兩個代碼 我都寫在 URL的那個 項目裏面了, 那樣 大家就不用 弄那麼多項目了 看着就有點煩。。。是吧 O(∩_∩)O~



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章