今天要为相册管理app添加一个地图观察功能,
主要是点击listview的图片后展开百度地图并在地图上标记出对应的图片,
并在该位置覆盖一个图片固定大小缩略图的一个图层。
(最后只附上地图模块的代码)
百度地图API的使用步骤:
1. http://developer.baidu.com/map/ 在该链接登陆百度地图API后,在API控制台注册一个APP的APIKEY,注册时需要SHA1指纹,只需(若使用Eclipse):Window->Preferences->Android->Build中复制即可。(本文所用百度地图版本2.4.2)得到移动端APIKEY之后,在AndroidManifest.xml中的<application> 加入meta-data子项,具体如:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <meta-data android:name="com.baidu.lbsapi.API_KEY" android:value="hgxHPQiRTvaRAkUy3bS2EnDA"/>
下面附上使用最简单地图功能的一段代码:
package com.example.photomanager0; import com.baidu.mapapi.BMapManager; import com.baidu.mapapi.MKGeneralListener; import com.baidu.mapapi.map.Ground; import com.baidu.mapapi.map.GroundOverlay; import com.baidu.mapapi.map.MKEvent; import com.baidu.mapapi.map.MKMapTouchListener; 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.mapapi.utils.DistanceUtil; import com.baidu.platform.comapi.basestruct.GeoPoint; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.ThumbnailUtils; import android.os.Bundle; import android.provider.MediaStore; import android.provider.MediaStore.Images.Thumbnails; import android.widget.Toast; public class ShowMapActivity extends Activity{ Bitmap bitmap =null; private Toast mToast; private BMapManager mBMapManager; private MapView mMapView = null; private MapController mMapController = null; private GeoPoint pPic; MKMapViewListener mMapListener = null; private GroundOverlay mGroundOverlay; private Ground mGround; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mBMapManager = new BMapManager(this.getApplication()); mBMapManager.init(new MKGeneralListener(){ @Override public void onGetNetworkState(int arg0) { // TODO Auto-generated method stub if (arg0 == MKEvent.ERROR_PERMISSION_DENIED){ showToast("Wrong API KEY..."); } } @Override public void onGetPermissionState(int arg0) { // TODO Auto-generated method stub if (arg0 == MKEvent.ERROR_NETWORK_CONNECT){ Toast.makeText(getApplication(), "Connecting Failed", Toast.LENGTH_LONG).show(); } } }); setContentView(R.layout.map_show); Long id = getIntent().getLongExtra("com.example.photomanager0.image",-1); BitmapFactory.Options op = new BitmapFactory.Options(); bitmap = ThumbnailUtils.extractThumbnail(MediaStore.Images.Thumbnails.getThumbnail( ShowMapActivity.this.getContentResolver(), id, Thumbnails.MINI_KIND, op), 200, 200); createScaledBitmap(); mMapView = (MapView) findViewById(R.id.bmapView); mMapController = mMapView.getController(); mMapController.enableClick(true); mMapController.setZoom(14); mMapView.setBuiltInZoomControls(true); GeoPoint p = new GeoPoint((int)(getIntent().getDoubleExtra("latitude", 39.945) * 1E6), (int)(getIntent().getDoubleExtra("longitude", 116.404)*1E6)); pPic = p; mMapController.setCenter(p); initOverlay(); mMapView.regMapTouchListner(new MKMapTouchListener(){ @Override public void onMapClick(GeoPoint arg0) { // TODO Auto-generated method stub if (DistanceUtil.getDistance(arg0, pPic)<250){ showToast("转到全景图模式..."); Intent intent = new Intent(ShowMapActivity.this, ShowPanoramaActivity.class); intent.putExtra("x", pPic.getLatitudeE6()); intent.putExtra("y", pPic.getLongitudeE6()); startActivity(intent); } } @Override public void onMapDoubleClick(GeoPoint arg0) { // TODO Auto-generated method stub } @Override public void onMapLongClick(GeoPoint arg0) { // TODO Auto-generated method stub } }); mMapListener = new MKMapViewListener() { @Override public void onMapMoveFinish() { /** * 在此处理地图移动完成回调 * 缩放,平移等操作完成后,此回调被触发 */ } @Override public void onClickMapPoi(MapPoi mapPoiInfo) { /** * 在此处理底图poi点击事件 * 显示底图poi名称并移动至该点 * 设置过: mMapController.enableClick(true); 时,此回调才能被触发 * */ if (mapPoiInfo != null){ mMapController.animateTo(mapPoiInfo.geoPt); } } @Override public void onGetCurrentMap(Bitmap b) { /** * 当调用过 mMapView.getCurrentMap()后,此回调会被触发 * 可在此保存截图至存储设备 */ } @Override public void onMapAnimationFinish() { /** * 地图完成带动画的操作(如: animationTo())后,此回调被触发 */ } /** * 在此处理地图载完成事件 */ @Override public void onMapLoadFinish() { showToast("加载完成"); } }; } public void initOverlay(){ /** * 创建自定义overlay */ mGroundOverlay = new GroundOverlay(mMapView); mGround = new Ground(bitmap, pPic, 500, 500); mMapView.getOverlays().add(mGroundOverlay); mGroundOverlay.addGround(mGround); /** * 刷新地图 */ mMapView.refresh(); mMapView.regMapViewListener(mBMapManager, mMapListener); } @Override protected void onResume(){ mMapView.onResume(); super.onResume(); } @Override protected void onPause() { //MapView的生命周期与Activity同步,当activity挂起时需调用MapView.onPause() mMapView.onPause(); super.onPause(); } @Override protected void onDestroy() { //MapView的生命周期与Activity同步,当activity销毁时需调用MapView.destroy() mMapView.destroy(); //退出应用调用BMapManager的destroy()方法 if(mBMapManager != null){ mBMapManager.destroy(); mBMapManager = null; } super.onDestroy(); } private void createScaledBitmap(){ } private void showToast(String msg){ if(mToast == null){ mToast = Toast.makeText(this, msg, Toast.LENGTH_SHORT); }else{ mToast.setText(msg); mToast.setDuration(Toast.LENGTH_SHORT); } mToast.show(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); mMapView.onSaveInstanceState(outState); } @Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mMapView.onRestoreInstanceState(savedInstanceState); } }
效果如图所示:
需要注意的是,百度地图的一些类的初始化和资源的使用要求都需要谨慎,最好参考过百度的demo。
BMapManager如果没有初始化的化是一定要初始化的,它可以管理多个地图组件,另外要注意把map的生命周期和activity绑定,当我们退出时需要保证没有资源的泄露。
下面一段,是一个最简单的全景图的使用:
package com.example.photomanager0; import com.baidu.mapapi.panorama.Panorama; import com.baidu.mapapi.panorama.PanoramaLink; import com.baidu.mapapi.panorama.PanoramaService; import com.baidu.mapapi.panorama.PanoramaView; import com.baidu.mapapi.panorama.PanoramaService.PanoramaServiceCallback; import com.baidu.mapapi.panorama.PanoramaViewCamera; import com.baidu.mapapi.panorama.PanoramaViewListener; import com.baidu.platform.comapi.basestruct.GeoPoint; import android.app.Activity; import android.app.ProgressDialog; import android.os.Bundle; import android.util.Log; import android.widget.Toast; public class ShowPanoramaActivity extends Activity{ private GeoPoint pPic; private PanoramaView mPanoramaView; private PanoramaService mService; private PanoramaServiceCallback mCallback; private ProgressDialog pd; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.panorama_show); pPic = new GeoPoint(getIntent().getIntExtra("x", 0), getIntent().getIntExtra("y", 0)); Log.i("cursor_i", getIntent().getIntExtra("x", 0)+" "+getIntent().getIntExtra("y", 0)); pd = new ProgressDialog(this); pd.setMessage("跳转中……"); pd.setCancelable(true);//设置进度条是否可以按退回键取消 mPanoramaView = (PanoramaView) findViewById(R.id.panorama); mService = PanoramaService.getInstance(getApplicationContext()); mCallback = new PanoramaServiceCallback() { public void onGetPanorama(Panorama p, int error) { //使用pid进入时添加标注 if ( error != 0){ Toast.makeText(ShowPanoramaActivity.this, "抱歉,未能检索到全景数据",Toast.LENGTH_LONG).show(); } if (p != null) { mPanoramaView.setPanorama(p); } } }; mService.requestPanoramaByGeoPoint(pPic, mCallback); mPanoramaView.setPanoramaViewListener(new PanoramaViewListener(){ @Override public void afterMovetoPanorama(String arg0) { // TODO Auto-generated method stub pd.dismiss(); } @Override public void beforeMoveToPanorama(String arg0) { // TODO Auto-generated method stub pd.show(); } @Override public void onClickPanoramaLink(PanoramaLink arg0) { // TODO Auto-generated method stub } @Override public void onPanoramaAnimationEnd() { // TODO Auto-generated method stub } @Override public void onPanoramaAnimationStart() { // TODO Auto-generated method stub } @Override public void onPanoramaCameraChange(PanoramaViewCamera arg0) { // TODO Auto-generated method stub } @Override public void onPanoramaMoveFinish() { // TODO Auto-generated method stub } @Override public void onPanoramaMoveStart() { // TODO Auto-generated method stub } }); } @Override protected void onPause() { super.onPause(); mPanoramaView.onPause(); } @Override protected void onResume() { super.onResume(); mPanoramaView.onResume(); } @Override protected void onDestroy() { mPanoramaView.destroy(); mService.destroy(); super.onDestroy(); } }
全景图部分主要由PanoramaView,PanoramaService,PanoramaServiceCallback 这三个部分组成:
PanoramaView完成对全景图的展示,而它的素材来源于PanoramaServiceCallback的回调函数提供的全景图,有了回调和位置pPic就可以建立一个PanoramaService完成对全景图服务的申请,笔者完成的Demo去掉了百度Demo中的一部分,可能较容易理解一些。最近好像3.0.0又去掉了全景图的功能,要使用全景图请下载2.4.2版本的百度地图。