2016年3月5日 星期六

Step By Step 簡易Mapsforge App開發:MapDownloadManager


目標Achievements


這個類別是用來去做圖資下載相關工作,我在範例中是使用第一種,但是為了學習方便我把另外一種也寫出來了


程式碼Code


1. 使用DownloadManager
package lien.ching.maptracker.api;

import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.util.Log;

import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
import org.mapsforge.map.android.util.AndroidUtil;
import org.mapsforge.map.android.view.MapView;
import org.mapsforge.map.datastore.MapDataStore;
import org.mapsforge.map.layer.Layer;
import org.mapsforge.map.layer.LayerManager;
import org.mapsforge.map.layer.Layers;
import org.mapsforge.map.layer.cache.TileCache;
import org.mapsforge.map.layer.labels.LabelLayer;
import org.mapsforge.map.layer.renderer.TileRendererLayer;
import org.mapsforge.map.reader.MapFile;
import org.mapsforge.map.rendertheme.InternalRenderTheme;

import java.io.File;
import java.net.URL;

import lien.ching.maptracker.Constant;
import lien.ching.maptracker.overlay.NowLocationLayout;


/**
 * Created by lienching on 12/21/15.
 */
public class mapDownloadManager implements  Runnable{


    private DownloadManager downloadManager;
    private Context context;
    private Long enqueue;
    public MapView mapview;
    public String target;
    private BroadcastReceiver receiver;
    private NowLocationLayout locationLayout;
    public mapDownloadManager(MapView mapView,NowLocationLayout locationLayout,Context context, final String target){
        super();
        this.context = context;
        this.target = target;
        this.mapview = mapView;
        this.locationLayout = locationLayout;
    }
    @Override
    public void run() {
        downloadManager = (DownloadManager) context.getSystemService(context.DOWNLOAD_SERVICE);
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse("http://download.mapsforge.org/maps/" + target));
        request.setDestinationInExternalPublicDir("mapsforge/maps/",target);
        enqueue = downloadManager.enqueue(request); //Active Download Process
        receiver = new LayerAdder(mapview,locationLayout,target,enqueue); //Created exclusive receiver
        context.registerReceiver(receiver,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)); //Registered Reciever
    }


}


2. 使用HTTP Download (Async)
package lien.ching.maptracker.api;

import android.app.Activity;
import android.app.DownloadManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.PowerManager;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import lien.ching.maptracker.Constant;
import lien.ching.maptracker.MainActivity;

/**
 * Created by lienching on 11/27/15.
 * In this class, I want to put downloading process in to Async
 * I directly implementing the HTTP Download in doInBackground()
 * In the app I didn't use this class as the download class
 * if you want to see the source code that use in the app
 * please check mapDownloadManager.class for more detail
 */
public class MapDownloadManager extends AsyncTask{
    private Context context;
    private Activity activity;
    private ProgressDialog dialog;
    public PowerManager.WakeLock wakeLock;
    public MapDownloadManager(Context context,Activity activity){
        super();
        this.activity = activity;
        this.context = context;
    }

    @Override
    protected Boolean doInBackground(String... params) {

        //For Details, please check http://stackoverflow.com/a/3028660
        String continent = params[1];
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        File outputFile = new File(Constant.PATH_MAPSFORGE+params[0]);

        try{
            URL url = new URL("http://download.mapsforge.org/maps/"+params[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            if(connection.getResponseCode() != HttpURLConnection.HTTP_OK){
                Toast.makeText(context,"Connection Fail..."+connection.getResponseCode(),Toast.LENGTH_SHORT).show();
                return false;
            }
            input = connection.getInputStream();
            if(outputFile.exists()){
                output = new FileOutputStream(outputFile);
            }
            else{
                EnvCheck envCheck = new EnvCheck(context,activity);
                envCheck.isMapResourceDirExist(continent);
                outputFile.createNewFile();
                output = new FileOutputStream(outputFile);

            }

            byte data[] = new byte[8192];
            int count;
            long total = 0;
            while((count = input.read(data)) != -1){
                if(isCancelled()) {
                    input.close();
                    return false;
                }
                total += count;
                output.write(data,0,count);
            }

            Log.d("MapDownloadManager","Write "+total+" bytes");
        }catch (Exception e){
            Log.e("MapDownloadManager","Writing Data:"+e.toString());
            return false;
        }finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }
            outputFile.setLastModified(connection.getLastModified());
            if (connection != null)
                connection.disconnect();
        }
        return false;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        PowerManager pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, activity.getClass().getName());
        wakeLock.acquire();
        dialog = new ProgressDialog(activity);
        dialog.setMessage("Map Source Downing");
        dialog.setCancelable(false);
        dialog.setIndeterminate(true);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.show();
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        if(dialog.isShowing()){
            dialog.dismiss();
        }
        if(wakeLock.isHeld())
            wakeLock.release();
        try {
            if (!aBoolean)
                Toast.makeText(context, "Download error", Toast.LENGTH_LONG).show();
            else
                Toast.makeText(context, "File downloaded", Toast.LENGTH_SHORT).show();
        }
        catch (Exception e){
            Log.d("MapUpdateManager", e.toString());
        }
    }
}


說明Explanation


第一種方式非常的單純也比較不需要擔心使用者不小心離開程式的時候會發生問題,但是缺點就是需要用Reciever去做下載完成判斷
第二種就是比較資工系的做法,直接實作HTTP Download,這個方法的好處就是可以對於"下載"這個動作做很多客製化的事情,但是要處理的事情就很多

沒有留言:

張貼留言