Android百度地圖之離線下載功能

jopen 11年前發布 | 83K 次閱讀 Android Android開發 移動開發

百度SDK中提供了離線下載功能,這樣在有網絡的時候可以把地圖下載下來,那么以后在無網的時候就可以使用地圖功能了,百度Demo代碼如下:

OffLineActivity:

package com.home;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.map.MKOLSearchRecord;
import com.baidu.mapapi.map.MKOLUpdateElement;
import com.baidu.mapapi.map.MKOfflineMap;
import com.baidu.mapapi.map.MKOfflineMapListener;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapView;

public class OffLineActivity extends Activity implements MKOfflineMapListener {

    private MapView mMapView = null;
    private MKOfflineMap mOffline = null;
    private TextView cidView;
    private TextView stateView;
    private EditText cityNameView;
    private MapController mMapController = null;
    /**
     * 已下載的離線地圖信息列表
     */
    private ArrayList<MKOLUpdateElement> localMapList = null;
    private LocalMapAdapter lAdapter = null;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        DemoApplication app = (DemoApplication) this.getApplication();
        if (app.mBMapManager == null) {
            app.mBMapManager = new BMapManager(this);
            app.mBMapManager.init(DemoApplication.strKey,
                    new DemoApplication.MyGeneralListener());
        }
        setContentView(R.layout.activity_offline);
        mMapView = new MapView(this);
        mMapController = mMapView.getController();

        mOffline = new MKOfflineMap();
        /**
         * 初始化離線地圖模塊,MapControler可從MapView.getController()獲取
         */
        mOffline.init(mMapController, this);
        initView();
    }

    private void initView() {
        cidView = (TextView) findViewById(R.id.cityid);
        cityNameView = (EditText) findViewById(R.id.city);
        stateView = (TextView) findViewById(R.id.state);

        ListView hotCityList = (ListView) findViewById(R.id.hotcitylist);
        ArrayList<String> hotCities = new ArrayList<String>();
        // 獲取熱門城市列表
        ArrayList<MKOLSearchRecord> records1 = mOffline.getHotCityList();
        if (records1 != null) {
            for (MKOLSearchRecord r : records1) {
                hotCities.add(r.cityName + "(" + r.cityID + ")" + "   --"
                        + this.formatDataSize(r.size));
            }
        }
        ListAdapter hAdapter = (ListAdapter) new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, hotCities);
        hotCityList.setAdapter(hAdapter);

        ListView allCityList = (ListView) findViewById(R.id.allcitylist);
        // 獲取所有支持離線地圖的城市
        ArrayList<String> allCities = new ArrayList<String>();
        ArrayList<MKOLSearchRecord> records2 = mOffline.getOfflineCityList();
        if (records1 != null) {
            for (MKOLSearchRecord r : records2) {
                allCities.add(r.cityName + "(" + r.cityID + ")" + "   --"
                        + this.formatDataSize(r.size));
            }
        }
        ListAdapter aAdapter = (ListAdapter) new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, allCities);
        allCityList.setAdapter(aAdapter);

        LinearLayout cl = (LinearLayout) findViewById(R.id.citylist_layout);
        LinearLayout lm = (LinearLayout) findViewById(R.id.localmap_layout);
        lm.setVisibility(View.GONE);
        cl.setVisibility(View.VISIBLE);

        // 獲取已下過的離線地圖信息
        localMapList = mOffline.getAllUpdateInfo();
        if (localMapList == null) {
            localMapList = new ArrayList<MKOLUpdateElement>();
        }

        ListView localMapListView = (ListView) findViewById(R.id.localmaplist);
        lAdapter = new LocalMapAdapter();
        localMapListView.setAdapter(lAdapter);

    }

    /**
     * 切換至城市列表
     * 
     * @param view
     */
    public void clickCityListButton(View view) {
        LinearLayout cl = (LinearLayout) findViewById(R.id.citylist_layout);
        LinearLayout lm = (LinearLayout) findViewById(R.id.localmap_layout);
        lm.setVisibility(View.GONE);
        cl.setVisibility(View.VISIBLE);
    }

    /**
     * 切換至下載管理列表
     * 
     * @param view
     */
    public void clickLocalMapListButton(View view) {
        LinearLayout cl = (LinearLayout) findViewById(R.id.citylist_layout);
        LinearLayout lm = (LinearLayout) findViewById(R.id.localmap_layout);
        lm.setVisibility(View.VISIBLE);
        cl.setVisibility(View.GONE);
    }

    /**
     * 搜索離線城市
     * 
     * @param view
     */
    public void search(View view) {
        ArrayList<MKOLSearchRecord> records = mOffline.searchCity(cityNameView
                .getText().toString());
        if (records == null || records.size() != 1)
            return;
        cidView.setText(String.valueOf(records.get(0).cityID));
    }

    /**
     * 開始下載
     * 
     * @param view
     */
    public void start(View view) {
        int cityid = Integer.parseInt(cidView.getText().toString());
        mOffline.start(cityid);
        clickLocalMapListButton(null);
        Toast.makeText(this, "開始下載離線地圖. cityid: " + cityid, Toast.LENGTH_SHORT)
                .show();
    }

    /**
     * 暫停下載
     * 
     * @param view
     */
    public void stop(View view) {
        int cityid = Integer.parseInt(cidView.getText().toString());
        mOffline.pause(cityid);
        Toast.makeText(this, "暫停下載離線地圖. cityid: " + cityid, Toast.LENGTH_SHORT)
                .show();
    }

    /**
     * 刪除離線地圖
     * 
     * @param view
     */
    public void remove(View view) {
        int cityid = Integer.parseInt(cidView.getText().toString());
        mOffline.remove(cityid);
        Toast.makeText(this, "刪除離線地圖. cityid: " + cityid, Toast.LENGTH_SHORT)
                .show();
    }

    /**
     * 從SD卡導入離線地圖安裝包
     * 
     * @param view
     */
    public void importFromSDCard(View view) {
        int num = mOffline.scan();
        String msg = "";
        if (num == 0) {
            msg = "沒有導入離線包,這可能是離線包放置位置不正確,或離線包已經導入過";
        } else {
            msg = String.format("成功導入 %d 個離線包,可以在下載管理查看", num);
        }
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
    }

    /**
     * 更新狀態顯示
     */
    public void updateView() {
        localMapList = mOffline.getAllUpdateInfo();
        if (localMapList == null) {
            localMapList = new ArrayList<MKOLUpdateElement>();
        }
        lAdapter.notifyDataSetChanged();
    }

    @Override
    protected void onPause() {
        int cityid = Integer.parseInt(cidView.getText().toString());
        mOffline.pause(cityid);
        mMapView.onPause();
        super.onPause();
    }

    @Override
    protected void onResume() {
        mMapView.onResume();
        super.onResume();
    }

    public String formatDataSize(int size) {
        String ret = "";
        if (size < (1024 * 1024)) {
            ret = String.format("%dK", size / 1024);
        } else {
            ret = String.format("%.1fM", size / (1024 * 1024.0));
        }
        return ret;
    }

    @Override
    protected void onDestroy() {
        /**
         * 退出時,銷毀離線地圖模塊
         */
        mOffline.destroy();
        mMapView.destroy();
        super.onDestroy();
    }

    @Override
    public void onGetOfflineMapState(int type, int state) {
        switch (type) {
        case MKOfflineMap.TYPE_DOWNLOAD_UPDATE: {
            MKOLUpdateElement update = mOffline.getUpdateInfo(state);
            // 處理下載進度更新提示
            if (update != null) {
                stateView.setText(String.format("%s : %d%%", update.cityName,
                        update.ratio));
                updateView();
            }
        }
            break;
        case MKOfflineMap.TYPE_NEW_OFFLINE:
            // 有新離線地圖安裝
            Log.d("OfflineDemo", String.format("add offlinemap num:%d", state));
            break;
        case MKOfflineMap.TYPE_VER_UPDATE:
            // 版本更新提示
            // MKOLUpdateElement e = mOffline.getUpdateInfo(state);
            break;
        }
    }

    /**
     * 離線地圖管理列表適配器
     */
    public class LocalMapAdapter extends BaseAdapter {

        @Override
        public int getCount() {
            return localMapList.size();
        }

        @Override
        public Object getItem(int index) {
            return localMapList.get(index);
        }

        @Override
        public long getItemId(int index) {
            return index;
        }

        @Override
        public View getView(int index, View view, ViewGroup arg2) {
            MKOLUpdateElement e = (MKOLUpdateElement) getItem(index);
            view = View.inflate(OffLineActivity.this,
                    R.layout.offline_localmap_list, null);
            initViewItem(view, e);
            return view;
        }

        void initViewItem(View view, final MKOLUpdateElement e) {
            Button display = (Button) view.findViewById(R.id.display);
            Button remove = (Button) view.findViewById(R.id.remove);
            TextView title = (TextView) view.findViewById(R.id.title);
            TextView update = (TextView) view.findViewById(R.id.update);
            TextView ratio = (TextView) view.findViewById(R.id.ratio);
            ratio.setText(e.ratio + "%");
            title.setText(e.cityName);
            if (e.update) {
                update.setText("可更新");
            } else {
                update.setText("最新");
            }
            if (e.ratio != 100) {
                display.setEnabled(false);
            } else {
                display.setEnabled(true);
            }
            remove.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View arg0) {
                    mOffline.remove(e.cityID);
                    updateView();
                }
            });
            display.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent();
                    intent.putExtra("x", e.geoPt.getLongitudeE6());
                    intent.putExtra("y", e.geoPt.getLatitudeE6());
                    intent.setClass(OffLineActivity.this,
                            BaseMapDemoActivity.class);
                    startActivity(intent);
                }
            });
        }

    }

}

BaseMapDemoActivity:

package com.home;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.widget.Toast;

import com.baidu.mapapi.BMapManager;
import com.baidu.mapapi.map.MKMapViewListener;
import com.baidu.mapapi.map.MapController;
import com.baidu.mapapi.map.MapPoi;
import com.baidu.mapapi.map.MapView;
import com.baidu.platform.comapi.basestruct.GeoPoint;

/**
 * 演示MapView的基本用法
 */
public class BaseMapDemoActivity extends Activity {

    final static String TAG = "MainActivity";
    /**
     * MapView 是地圖主控件
     */
    private MapView mMapView = null;
    /**
     * 用MapController完成地圖控制
     */
    private MapController mMapController = null;
    /**
     * MKMapViewListener 用于處理地圖事件回調
     */
    MKMapViewListener mMapListener = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        /**
         * 使用地圖sdk前需先初始化BMapManager. BMapManager是全局的,可為多個MapView共用,它需要地圖模塊創建前創建,
         * 并在地圖地圖模塊銷毀后銷毀,只要還有地圖模塊在使用,BMapManager就不應該銷毀
         */
        DemoApplication app = (DemoApplication) this.getApplication();
        if (app.mBMapManager == null) {
            app.mBMapManager = new BMapManager(this);
            /**
             * 如果BMapManager沒有初始化則初始化BMapManager
             */
            app.mBMapManager.init(DemoApplication.strKey,
                    new DemoApplication.MyGeneralListener());
        }
        /**
         * 由于MapView在setContentView()中初始化,所以它需要在BMapManager初始化之后
         */
        setContentView(R.layout.activity_main);
        mMapView = (MapView) findViewById(R.id.bmapView);
        /**
         * 獲取地圖控制器
         */
        mMapController = mMapView.getController();
        /**
         * 設置地圖是否響應點擊事件 .
         */
        mMapController.enableClick(true);
        /**
         * 設置地圖縮放級別
         */
        mMapController.setZoom(12);

        /**
         * 將地圖移動至指定點
         * 使用百度經緯度坐標,可以通過http://api.map.baidu.com/lbsapi/getpoint/index
         * .html查詢地理坐標 如果需要在百度地圖上顯示使用其他坐標系統的位置,請發郵件至mapapi@baidu.com申請坐標轉換接口
         */
        GeoPoint p;
        double cLat = 39.945;
        double cLon = 116.404;
        Intent intent = getIntent();
        if (intent.hasExtra("x") && intent.hasExtra("y")) {
            // 當用intent參數時,設置中心點為指定點
            Bundle b = intent.getExtras();
            p = new GeoPoint(b.getInt("y"), b.getInt("x"));
        } else {
            // 設置中心點為天安門
            p = new GeoPoint((int) (cLat * 1E6), (int) (cLon * 1E6));
        }

        mMapController.setCenter(p);

        /**
         * MapView的生命周期與Activity同步,當activity掛起時需調用MapView.onPause()
         */
        mMapListener = new MKMapViewListener() {
            @Override
            public void onMapMoveFinish() {
                /**
                 * 在此處理地圖移動完成回調 縮放,平移等操作完成后,此回調被觸發
                 */
            }

            @Override
            public void onClickMapPoi(MapPoi mapPoiInfo) {
                /**
                 * 在此處理底圖poi點擊事件 顯示底圖poi名稱并移動至該點 設置過:
                 * mMapController.enableClick(true); 時,此回調才能被觸發
                 * 
                 */
                String title = "";
                if (mapPoiInfo != null) {
                    title = mapPoiInfo.strText;
                    Toast.makeText(BaseMapDemoActivity.this, title,
                            Toast.LENGTH_SHORT).show();
                    mMapController.animateTo(mapPoiInfo.geoPt);
                }
            }

            @Override
            public void onGetCurrentMap(Bitmap b) {
                /**
                 * 當調用過 mMapView.getCurrentMap()后,此回調會被觸發 可在此保存截圖至存儲設備
                 */
            }

            @Override
            public void onMapAnimationFinish() {
                /**
                 * 地圖完成帶動畫的操作(如: animationTo())后,此回調被觸發
                 */
            }

            /**
             * 在此處理地圖加載完成事件
             */
            @Override
            public void onMapLoadFinish() {
                Toast.makeText(BaseMapDemoActivity.this, "地圖加載完成",
                        Toast.LENGTH_SHORT).show();

            }
        };
        mMapView.regMapViewListener(DemoApplication.getInstance().mBMapManager,
                mMapListener);
    }

    @Override
    protected void onPause() {
        /**
         * MapView的生命周期與Activity同步,當activity掛起時需調用MapView.onPause()
         */
        mMapView.onPause();
        super.onPause();
    }

    @Override
    protected void onResume() {
        /**
         * MapView的生命周期與Activity同步,當activity恢復時需調用MapView.onResume()
         */
        mMapView.onResume();
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        /**
         * MapView的生命周期與Activity同步,當activity銷毀時需調用MapView.destroy()
         */
        mMapView.destroy();
        super.onDestroy();
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mMapView.onSaveInstanceState(outState);

    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        mMapView.onRestoreInstanceState(savedInstanceState);
    }

}

activity_offline:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="50dip"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/cityid"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="131" />
        <!-- 隱藏輸入法用 -->

        <LinearLayout
            android:layout_width="0px"
            android:layout_height="0px"
            android:focusable="true"
            android:focusableInTouchMode="true" />

        <EditText
            android:id="@+id/city"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="北京" />

        <Button
            android:id="@+id/search"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:onClick="search"
            android:text="搜索" />

        <Button
            android:id="@+id/scan"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:onClick="importFromSDCard"
            android:text="導入" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="50dip"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/state"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="已下載:--" />

        <Button
            android:id="@+id/start"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:onClick="start"
            android:text="開始" />

        <Button
            android:id="@+id/stop"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:onClick="stop"
            android:text="暫停" />

        <Button
            android:id="@+id/del"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:onClick="remove"
            android:text="刪除" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/city_list"
        android:layout_width="match_parent"
        android:layout_height="50dip"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/clButton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:onClick="clickCityListButton"
            android:text="城市列表" />

        <Button
            android:id="@+id/localButton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:background="@drawable/button_style"
            android:onClick="clickLocalMapListButton"
            android:text="下載管理" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/citylist_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="熱門城市" />

        <ListView
            android:id="@+id/hotcitylist"
            android:layout_width="fill_parent"
            android:layout_height="200dip" />

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="全國" />

        <ListView
            android:id="@+id/allcitylist"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </LinearLayout>

    <LinearLayout
        android:id="@+id/localmap_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="已下載城市 " />

        <ListView
            android:id="@+id/localmaplist"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

offline_localmap_list:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="10dip" >

    <TextView
        android:id="@+id/title"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="已下載城市 " />

    <TextView
        android:id="@+id/update"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text=""
        android:textColor="#FF0000" />

    <TextView
        android:id="@+id/ratio"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="" />

    <Button
        android:id="@+id/display"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/button_style"
        android:text="查看" />

    <Button
        android:id="@+id/remove"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:background="@drawable/button_style"
        android:text="刪除" />

</LinearLayout>

activity_main:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <com.baidu.mapapi.map.MapView
        android:id="@+id/bmapView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:clickable="true" />

</LinearLayout>

配置文件及Application類同之前一樣。

附上圖片效果:

d3.jpeg

d4.jpeg

來自:http://blog.csdn.net/u010142437/article/details/11583745

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!