2016年3月5日 星期六

Step By Step 簡易Mapsforge App開發:MapUpdateManager


目標Achievements


這個類別是用來做圖資更新檢查與更新


程式碼Code


package lien.ching.maptracker.api;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
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;

/**
 * Created by lienching on 12/1/15.
 * In this class, I had no idea how to update a file by using DownloadManager
 * so I just try to use standard HTTP Download as the method
 */
public class MapUpdateManager extends AsyncTask {

    private ProgressDialog dialog;
    private PowerManager.WakeLock wakeLock;
    private Context context;
    private Activity activity;
    public MapUpdateManager(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.lastModified() < connection.getLastModified()){ //if the date is older than the latest file then close the download process
                input.close();
                output.close();
                return true;
            }
            dialog.setMessage("Map Source Updating");
            outputFile.delete();
            outputFile.createNewFile();
            output = new FileOutputStream(outputFile);
            byte data[] = new byte[8192];
            int count;
            while((count = input.read(data)) != -1){
                if(isCancelled()){
                    input.close();
                    return false;
                }

                output.write(data,0,count);
            }
        }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) { }

            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 Checking");
        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


這個整體程式使用的下載方式請參照這裡
這邊程式運作的方式是Async,可以在這邊瞭解更多
第57~61行:檢查圖資是不是比資料庫的還要舊,如果是就不繼續做更新的動作,否則就繼續做

Step By Step 簡易Mapsforge App開發:EnvCheck


目標Achievements


這個類別的工作是去偵測使用者是否有我們所需的地圖資料,若有那就去偵測是否有新的版本,否則就去下載。這個類別還做了一件事就是將圖資進行渲染(為了讓圖資檔案比較小,所以使用了向量圖的儲存方式)並喂給MapView去做顯示。


程式碼Code


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.os.Environment;
import android.util.Log;
import android.widget.Toast;

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.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.util.concurrent.TimeUnit;

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

/**
 * Created by lienching on 11/27/15.
 * This class is use for checking if the device have the required map file or not.
 */
public class EnvCheck {
    private Context context;
    private String externalpath = Environment.getExternalStorageDirectory().getPath();
    private MapDownloadManager mapDownloadManager;
    private MapUpdateManager mapUpdateManager;
    private mapDownloadManager downloadManger;
    private Activity activity;
    private MapView mapView;
    private NowLocationLayout locationLayout;
    public EnvCheck(MapView mapView,NowLocationLayout locationLayout,Context context,Activity activity){
        this.activity = activity;
        this.context = context;
        this.mapView = mapView;
        this.locationLayout = locationLayout;
    }
    public EnvCheck(Context context,Activity activity){
        this.activity = activity;
        this.context = context;
        this.mapView = null;
    }

    public void CheckAndDownload(String continent, String sourcefile) {
        String mapfile = continent+"/"+sourcefile;
        if(!this.isMapResourceExist(mapfile)) {
            downloadManger = new mapDownloadManager(mapView,locationLayout, context, mapfile);
            Thread thread = new Thread(downloadManger);
            thread.run();
        }
        else{
            MapFile targetFile = new MapFile(new File(Constant.PATH_MAPSFORGE+mapfile));
            TileCache tileCache = AndroidUtil.createTileCache(context, "mapcache", mapView.getModel().displayModel.getTileSize(), 1f, mapView.getModel().frameBufferModel.getOverdrawFactor());
            TileRendererLayer tileRendererLayer = AndroidUtil.createTileRendererLayer(tileCache,mapView.getModel().mapViewPosition,targetFile, InternalRenderTheme.OSMARENDER,true,true);
            tileRendererLayer.setXmlRenderTheme(InternalRenderTheme.OSMARENDER);
            mapView.getLayerManager().getLayers().add(tileRendererLayer);
        }
    }


    public boolean isMapResourceDirExist(final String continent){
        File dir = new File(Constant.PATH_MAPSFORGE+continent);
        if(!dir.exists()) {
            if (!dir.mkdirs()) {
                Log.e("EnvCheck","Dir create failed");
                return false;
            }
            Log.d("EnvCheck","Dir Create Sucess!");
        }
        return true;
    }
    public boolean isMapResourceExist(final String mapfile){
        if(!(new File(externalpath+"/mapsforge").exists()))
            createDirectory();
        File searchFile = new File(externalpath+"/mapsforge/maps/"+mapfile);
        if(searchFile.exists())
            return true;
        return false;
    }

    public void createDirectory(){
        File target = new File(externalpath+"/mapsforge/maps");
        target.mkdirs();
        if(target.exists()&&target.isDirectory()){
            Toast.makeText(context, R.string.toast_dir_success, Toast.LENGTH_SHORT).show();
        }
        else{
            Toast.makeText(context, R.string.toast_dir_fail_retry,Toast.LENGTH_SHORT).show();
            target.mkdir();
            if(target.exists()&&target.isDirectory()){
                Toast.makeText(context, R.string.toast_dir_success, Toast.LENGTH_SHORT).show();
            }
            else{
                Toast.makeText(context, R.string.toast_dir_fail, Toast.LENGTH_SHORT).show();
            }
        }
    }
}


說明Explanation


第64行:建立圖資渲染暫存區,For Detail 第65~66行: 建立圖資圖層並設定地圖風格

Step By Step 簡易Mapsforge App開發:NowLocationLayout


目標Achievements


這個類別顧名思義就是要去顯示目前使用者的地理位置並顯示在我們的地圖上面。


程式碼Code


package lien.ching.maptracker.overlay;

import android.Manifest;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.GpsSatellite;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.util.Log;
import android.widget.TextView;

import org.mapsforge.core.graphics.Bitmap;
import org.mapsforge.core.graphics.Canvas;
import org.mapsforge.core.graphics.GraphicFactory;
import org.mapsforge.core.graphics.Paint;
import org.mapsforge.core.graphics.Style;
import org.mapsforge.core.model.BoundingBox;
import org.mapsforge.core.model.LatLong;
import org.mapsforge.core.model.Point;
import org.mapsforge.map.android.graphics.AndroidGraphicFactory;
import org.mapsforge.map.android.view.MapView;
import org.mapsforge.map.layer.Layer;
import org.mapsforge.map.layer.overlay.Circle;
import org.mapsforge.map.layer.overlay.Marker;
import org.mapsforge.map.layer.overlay.Polyline;
import org.mapsforge.map.model.MapViewPosition;
import org.mapsforge.map.android.util.AndroidSupportUtil;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import lien.ching.maptracker.R;

/**
 * Created by lienching on 12/2/15.
 */


//This class is using LocationManager to provided location information it may cause some issue, for more reliable location information use  Google Play services location APIs(http://developer.android.com/training/location/index.html)

public class NowLocationLayout extends Layer implements LocationListener,GpsStatus.Listener,ActivityCompat.OnRequestPermissionsResultCallback {


    private Activity activity;
    private MapViewPosition mapViewPosition;
    private MapView mapView;
    private LocationManager locationManager;
    private List history_path;

    private Boolean track;

    //For drawing purpose (http://mapsforge.org/docs/0.6.0/org/mapsforge/map/android/graphics/AndroidGraphicFactory.html)
    private static final GraphicFactory GRAPHIC_FACTORY = AndroidGraphicFactory.INSTANCE;
    private Circle accuray_circle;
    private Marker loc_marker;
    private Polyline usr_path;




    //Constructor
    public NowLocationLayout(Activity activity,MapViewPosition mapViewPosition,MapView mapView){
        this.activity = activity;
        this.mapViewPosition = mapViewPosition;
        this.mapView = mapView;
        this.locationManager = (LocationManager) activity.getSystemService(activity.LOCATION_SERVICE);

        track = false;

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000L,0, this);
        //Check if location services available
        if(!locationManager.isProviderEnabled (LocationManager.GPS_PROVIDER)){
            activity.startActivityForResult(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), 0);
        }

        locationManager.addGpsStatusListener(this);//To add satellite listener


        //setDisplayModel(this.displayModel) set circle, polyline, marker etc... in to mapview's display model, so DisplayModel.getTileSize() won't point to a null object.
        accuray_circle = new Circle(null,0,getDefaultCircleFill(),getDefaultCircleStroke());//Circle(LatLong,radius,color,stroke);
        accuray_circle.setDisplayModel(mapView.getModel().displayModel);

        usr_path = new Polyline(getDefaultPolylineStroke(),GRAPHIC_FACTORY);
        usr_path.setDisplayModel(mapView.getModel().displayModel);

        //AndroidGraphicFactory.convertToBitmap() for detail please check AndroidGraphicFactory
        Drawable drawable = activity.getResources().getDrawable(R.drawable.locationmarker);
        Bitmap bitmap = AndroidGraphicFactory.convertToBitmap(drawable);
        loc_marker = new Marker(null, bitmap, 1, 0);
        loc_marker.setDisplayModel(mapView.getModel().displayModel);

        history_path = new LinkedList();//record user path
    }

    //Transfer Function

    private LatLong LocationToLatLong(Location location){
        LatLong latlong = new LatLong(location.getLatitude(),location.getLongitude());
        return latlong;
    }

    //Getter
    protected Paint getPaint(int color, float strokeWidth, Style style){
        Paint paint = GRAPHIC_FACTORY.createPaint();
        paint.setColor(color);
        paint.setStrokeWidth(strokeWidth);
        paint.setStyle(style);
        return paint;
    }

    private Paint getDefaultCircleFill() {
        return this.getPaint(GRAPHIC_FACTORY.createColor(48, 0, 0, 255), 0, Style.FILL);
    }

    private Paint getDefaultCircleStroke() {
        return this.getPaint(GRAPHIC_FACTORY.createColor(160, 0, 0, 255), 2, Style.STROKE);
    }

    private Paint getDefaultPolylineStroke() {
        return this.getPaint(GRAPHIC_FACTORY.createColor(160, 0, 255, 0), 20, Style.STROKE);
    }


    //Enable Location Tracking
    public void startTrack(){
        this.track = true;
    }


    @Override
    public void draw(BoundingBox boundingBox, byte zoomLevel, Canvas canvas, Point topLeftPoint) {
        if(track) {
            loc_marker.draw(boundingBox, zoomLevel, canvas, topLeftPoint);
            accuray_circle.draw(boundingBox, zoomLevel, canvas, topLeftPoint);
        }
        List temp = usr_path.getLatLongs(); //To get all the LatLong that had been drew
        temp.removeAll(temp); //Remove all
        temp.addAll(history_path);//To re-add all path
        usr_path.draw(boundingBox, zoomLevel, canvas, topLeftPoint);
    }

    @Override
    public void onGpsStatusChanged(int event) {

    }

    @Override
    public void onLocationChanged(Location location) {

        LatLong latLong = this.LocationToLatLong(location);
        loc_marker.setLatLong(latLong);
        accuray_circle.setLatLong(latLong);
        history_path.add(latLong);

        accuray_circle.setRadius(location.getAccuracy());

        mapViewPosition.setCenter(latLong);
        mapViewPosition.setZoomLevel((byte) 17);
        requestRedraw();

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {}

    @Override
    public void onProviderEnabled(String provider) {
        locationManager.requestLocationUpdates(provider, 1000L, 0, this);
        if(locationManager.GPS_PROVIDER.equals(provider)) {
            track = true;
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
        if(locationManager.GPS_PROVIDER.equals(provider)){
            track = false;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {}

}


說明Explanation


第79行:這行是用來設定GPS更新頻率,參數大概為(地理資訊提供(GPS, Network), 更新時間(單位:毫秒), 更新距離(當距離超過就更新), 接收資訊的Listener),For Detail
第90、93、99行:如果不把那些物件的DisplayModel設定成MapView的,會出現NullPointerException
第145~147行:第145行是Pass by Reference所以我們可以直接用temp去操作,然後我們先把原本的List清空,再把歷史紀錄再放回去
第164行:這句是利用GPS準確度來當作圓的半徑,For Detail

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,這個方法的好處就是可以對於"下載"這個動作做很多客製化的事情,但是要處理的事情就很多

Step By Step 簡易Mapsforge App開發:LayerAdder


目標Achievements


這個類別目的是要用來做動態新增圖層


程式碼Code


package lien.ching.maptracker.api;

import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
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.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 org.mapsforge.map.rendertheme.rule.RenderTheme;

import java.io.File;

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

/**
 * Created by lienching on 1/7/16.
 */

//http://developer.android.com/reference/android/content/BroadcastReceiver.html
public class LayerAdder extends BroadcastReceiver {
    private MapView mapView;
    private String target;
    private NowLocationLayout locationLayout;
    private Long enqueue;
    public LayerAdder(MapView mapView,NowLocationLayout locationLayout,String target,Long enqueue){
        super();
        this.mapView = mapView;
        this.target = target;
        this.enqueue = enqueue;
        this.locationLayout = locationLayout;
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
            long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
            if(downloadId == enqueue){
                MapFile targetFile = new MapFile(new File(Constant.PATH_MAPSFORGE+target));
                TileCache tileCache = AndroidUtil.createTileCache(context, "mapcache", mapView.getModel().displayModel.getTileSize(), 1f, mapView.getModel().frameBufferModel.getOverdrawFactor());
                TileRendererLayer tileRendererLayer = AndroidUtil.createTileRendererLayer(tileCache,mapView.getModel().mapViewPosition,targetFile, InternalRenderTheme.OSMARENDER,true,true);
                tileRendererLayer.setXmlRenderTheme(InternalRenderTheme.OSMARENDER);
                mapView.getLayerManager().getLayers().add(tileRendererLayer);
                mapView.getLayerManager().getLayers().remove(locationLayout);//LocationLayout need be the top layout of the mapview, to keep user location visible
                mapView.getLayerManager().getLayers().add(locationLayout);
                Log.d("LayerAdder",target+" Download Completed"+", LayerAdd");
            }
        }
    }
}
 

說明Explanation


BroadcastReceiver是我用來去偵測檔案是否下載完成的類別