第一篇:Android地图和定位学习总结
Android地图和定位学习总结
首届 Google 暑期大学生博客分享大赛——2010 Android 篇 android.location包下有这么一些接口和类: Interfaces GpsStatus.Listener GpsStatus.NmeaListener LocationListener Classes Address Criteria Geocoder GpsSatellite GpsStatus Location LocationManager LocationProvider com.google.android.maps包下有这些类: All Classes GeoPoint ItemizedOverlay ItemizedOverlay.OnFocusChangeListener MapActivity MapController MapView MapView.LayoutParams MapView.ReticleDrawMode MyLocationOverlay Overlay Overlay.Snappable OverlayItem Projection TrackballGestureDetector 我们边看代码边熟悉这些类。
要获取当前位置坐标,就是从Location对象中获取latitude和longitude属性。那Location对象是如何创建的? LocationManager
locMan=(LocationManager)getSystemService(Context.LOCATION_SERVICE);//LocationManager对象只能这么创建,不能用new Locationlocation=locMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);if(location==null){
location=locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);} //注意要为应用程序添加使用权限
自然是获取最新的地理位置信息,那LocationManager.GPS_PROVIDER和LocationManager.NETWORK_PROVIDER有什么区别呢?俺也不是学通信的,对这个不了解,在网上看到有人想“在室外有GPS定位,在室内想用Wifi或基站定位”。
除了直接使用LocationManager提供的静态Provider(如GPS_PROVIDER和NETWORK_PROVIDER等)外,还可以使用我们自己创建的LocationProvider对象。创建LocationProvider对象一般要先创建Criteria对象,来设置我们的LocationProvider要满足什么样的标准 Criteria myCri=new Criteria();myCri.setAccuracy(Criteria.ACCURACY_FINE);//精确度 myCri.setAltitudeRequired(false);//海拔不需要
myCri.setBearingRequired(false);//Bearing是“轴承”的意思,此处可理解为地轴线之类的东西,总之Bearing Information是一种地理位置信息的描述 myCri.setCostAllowed(true);//允许产生现金消费
myCri.setPowerRequirement(Criteria.POWER_LOW);//耗电 String myProvider=locMan.getBestProvider(myCri,true);public String getBestProvider(Criteria criteria, boolean enabledOnly)Returns the name of the provider that best meets the given criteria.Only providers that are permitted to be accessed by the calling activity will be returned.If several providers meet the criteria, the one with the best accuracy is returned.If no provider meets the criteria, the criteria are loosened in the following sequence: power requirement accuracy bearing speed altitude Note that the requirement on monetary cost is not removed in this process.Parameters
criteria
the criteria that need to be matched enabledOnly
if true then only a provider that is currently enabled is returned Returns
name of the provider that best matches the requirements only翻译为“最适合的“ Location location=locMan.getLastKnownLoation(myProvider);double latitude=location.getLatitude();//获取纬度 double longitude=location.getLongitude();//获取经度
我想知道当前位置描述(比如“武汉华中科技大学”而不是一个经纬值)呢?这就要使用GeoCoder创建一个Address对象了。
Geocoder gc=new Geocoder(context,Locale.CHINA);//Locale是java.util中的一个类 List
listAddress=gc.getFromLocation(latitude,longitude,1);ListgetFromLocation(double latitude, double longitude, int maxResults)Returns an array of Addresses that are known to describe the area immediately surrounding the given latitude and longitude.(返回给定经纬值附近的一个Address)既然是“附近”那实际编码时我们没必要把经纬值给的那么精确,而取一个近似的整数,像这样: /*自经纬度取得地址,可能有多行地址*/ List
listAddress=gc.getFromLocation((int)latitude,(int)longitude,1);StringBuilder sb=new StringBuilder();/*判断是不否为多行*/ if(listAddress.size()>0){Address address=listAddress.get(0);
for(int i=0;i
sb.append(address.getAddressLine(i)).append(”n“);
}
sb.append(address.getLocality()).append(”n“);
sb.append(address.getPostalCode()).append(”n“);
sb.append(address.getCountryName()).append(”n“);} public int getMaxAddressLineIndex()
Since: API Level 1 Returns the largest index currently in use to specify an address line.If no address lines are specified,-1 is returned.public String getAddressLine(int index)
Since: API Level 1 Returns a line of the address numbered by the given index(starting at 0), or null if no such line is present.String
getCountryName()Returns the localized country name of the address, for example ”Iceland“, or null if it is unknown.String
getLocality()Returns the locality of the address, for example ”Mountain View“, or null if it is unknown.反过来我们可以输入地址信息获取经纬值
Geocoder mygeoCoder=new Geocoder(myClass.this,Locale.getDefault());List
lstAddress=mygeoCoder.getFromLocationName(strAddress,1);//strAddress是输入的地址信息 if(!lstAddress.isEmpty()){
Address address=lstAddress.get(0);
double latitude=address.getLatitude()*1E6;
double longitude=adress.getLongitude()*1E6;
GeoPoint geopoint=new GeoPoint((int)latitude,(int)longitude);}
A class for handling geocoding and reverse geocoding.Geocoding is the process of transforming a street address or other description of a location into a(latitude, longitude)coordinate.Public Constructors Geocoder(Context context, Locale locale)Constructs a Geocoder whose responses will be localized for the given Locale.Geocoder(Context context)Constructs a Geocoder whose responses will be localized for the default system Locale.public List
maxResults)Since: API Level 1
getFromLocationName(String locationName, int Returns an array of Addresses that are known to describe the named location, which may be a place name
such as ”Dalvik, Iceland“, an address such as ”1600 Amphitheatre Parkway, Mountain View, CA“, an airport
code such as ”SFO", etc..The returned addresses will be localized for the locale provided to this class's constructor.The query will block and returned values will be obtained by means of a network lookup.The results are a best
guess and are not guaranteed to be meaningful or correct.It may be useful to call this method from a thread
separate from your primary UI thread.Parameters locationName
maxResults Returns a user-supplied description of a location
max number of results to return.Smaller numbers(1 to 5)are recommended a list of Address objects.Returns null or empty list if no matches were found or service available.there is no backend
Throws IllegalArgumentException
IOException
说了半天还只是个定位,地图还没出来。下面要用到com.google.android.maps包了 下面的代码我们让地图移到指定点
GeoPoint p=new GeoPoint((int)(latitude*1E6),(int)(longitude*1E6));MapView mapview=(MapView)findViewById(R.id.mv);MapController mapContr=mapview.getController();mapview.displayZoomControls(true);//显示地图缩放的按钮 mapContr.animateTo(p);//带动画移到p点 mapContr.setZoom(7);setZoom public int setZoom(int zoomLevel)Sets the zoomlevel of the map.The value will be clamped to be between 1 and 21 inclusive, though
not all areas have tiles at higher zoom levels.This just sets the level of the zoom directly;for a
step-by-step zoom with fancy interstitial animations, use
if locationName is null
if the network is unavailable or any other I/O problem occurs
zoomIn()or zoomOut().Parameters:
zoomLevelThe Canvas upon which to draw.Note that this may already have a transformation applied, so be sure to leave it the way you found it.mapViewIf true, draw the shadow layer.If false, draw the overlay contents.public boolean draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow, long when)when-The timestamp of the draw.Draw call for animated overlays.By default, calls through to draw(Canvas, MapView, boolean)and returns false.Canvas公共方法
void
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
Draw the specified bitmap, scaling/translating automatically to fill the destination rectangle.
第二篇:android百度地图api实现短信接收定位
工程文件结构:
demoApplication.java package com.gy.mymaps;
import android.app.Application;import android.content.Context;import android.widget.Toast;
import com.baidu.mapapi.BMapManager;import com.baidu.mapapi.MKGeneralListener;import com.baidu.mapapi.map.MKEvent;
public class DemoApplication extends Application {
private static DemoApplication mInstance = null;
public boolean m_bKeyRight = true;
BMapManager mBMapManager = null;
@Override
public void onCreate(){
super.onCreate();
mInstance = this;
initEngineManager(this);}
public void initEngineManager(Context context){
if(mBMapManager == null){
mBMapManager = new BMapManager(context);
}
if(!mBMapManager.init(new MyGeneralListener())){
Toast.makeText(DemoApplication.getInstance().getApplicationContext(),“BMapManager初始化错误!”, Toast.LENGTH_LONG).show();
} }
public static DemoApplication getInstance(){
return mInstance;}
// 常用事件监听,用来处理通常的网络错误,授权验证错误等
static class MyGeneralListener implements MKGeneralListener {
public void onGetNetworkState(int iError){
if(iError == MKEvent.ERROR_NETWORK_CONNECT){
Toast.makeText(DemoApplication.getInstance().getApplicationContext(), “您的网络出错啦!”,Toast.LENGTH_LONG).show();
}
else if(iError == MKEvent.ERROR_NETWORK_DATA){
Toast.makeText(DemoApplication.getInstance().getApplicationContext(), “输入正确的检索条件!”,Toast.LENGTH_LONG).show();
}
//...}
public void onGetPermissionState(int iError){
//非零值表示key验证未通过
if(iError!= 0){
//鎺堟潈Key閿欒锛�
Toast.makeText(DemoApplication.getInstance().getApplicationContext(),“请输入正确的授权Key,并检查您的网络连接是否正常!error: ”+iError, Toast.LENGTH_LONG).show();
DemoApplication.getInstance().m_bKeyRight = false;
}
else{
DemoApplication.getInstance().m_bKeyRight = true;
Toast.makeText(DemoApplication.getInstance().getApplicationContext(),“key认证成功”, Toast.LENGTH_LONG).show();
}
}
} } Mainactivity.java: package com.gy.mymaps;
import java.util.List;
import android.annotation.SuppressLint;import android.app.Activity;import android.content.ContentValues;import android.database.ContentObserver;import android.database.Cursor;import android.graphics.drawable.Drawable;import android.net.Uri;import android.os.Build;import android.os.Bundle;import android.os.Handler;import android.telephony.SmsManager;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;
import com.baidu.mapapi.BMapManager;import com.baidu.mapapi.map.ItemizedOverlay;import com.baidu.mapapi.map.MapView;import com.baidu.mapapi.map.OverlayItem;import com.baidu.mapapi.search.MKAddrInfo;import com.baidu.mapapi.search.MKBusLineResult;import com.baidu.mapapi.search.MKDrivingRouteResult;import com.baidu.mapapi.search.MKPoiResult;import com.baidu.mapapi.search.MKSearch;import com.baidu.mapapi.search.MKSearchListener;import com.baidu.mapapi.search.MKShareUrlResult;import com.baidu.mapapi.search.MKSuggestionResult;import com.baidu.mapapi.search.MKTransitRouteResult;import com.baidu.mapapi.search.MKWalkingRouteResult;import com.baidu.platform.comapi.basestruct.GeoPoint;//import com.gy.msmsend.R;public class MainActivity extends Activity { //UI相关
Button mBtnReverseGeoCode = null;// 将坐标反编码为地址
Button mBtnGeoCode = null;// 将地址编码为坐标
Button msmSend =null;//短信发送按钮
//地图相关
MapView mMapView = null;// 地图View
//搜索相关
MKSearch mSearch = null;// 搜索模块,也可去掉地图模块独立使用
EditText phoneText;
String[] as;
String city=null;
String pos=null;
Drawable marker;
int png=0;
//
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
/*
* 注册短信变化事件监听
*/
SmsContent content = new SmsContent(new Handler());
//注册短信变化监听
this.getContentResolver().registerContentObserver(Uri.parse(“content://sms/”), true, content);
//注册短信变化监听
/**
* 使用地图sdk前需先初始化BMapManager.* BMapManager是全局的,可为多个MapView共用,它需要地图模块创建前创建,* 并在地图地图模块销毁后销毁,只要还有地图模块在使用,BMapManager就不应该销毁
*/
DemoApplication app =(DemoApplication)this.getApplication();
if(app.mBMapManager == null){
app.mBMapManager = new BMapManager(getApplicationContext());
/**
* 如果BMapManager没有初始化则初始化BMapManager
*/
app.mBMapManager.init(new DemoApplication.MyGeneralListener());
}
setContentView(R.layout.activity_main);
CharSequence titleLable=“我的位置”;
setTitle(titleLable);
//地图初始化
mMapView =(MapView)findViewById(R.id.bmapView);
mMapView.getController().enableClick(true);
mMapView.getController().setZoom(12);
// 初始化搜索模块,注册事件监听
mSearch = new MKSearch();
mSearch.init(app.mBMapManager, new MKSearchListener(){
public void onGetPoiDetailSearchResult(int type, int error){
}
public void onGetAddrResult(MKAddrInfo res, int error){
if(error!= 0){
String str = String.format(“错误号:%d”, error);
Toast.makeText(MainActivity.this, str, Toast.LENGTH_LONG).show();
return;
}
//地图移动到该点
mMapView.getController().animateTo(res.geoPt);
if(res.type == MKAddrInfo.MK_GEOCODE){
//地理编码:通过地址检索坐标点
String strInfo = String.format(“纬度:%f 经度:%f”, res.geoPt.getLatitudeE6()/1e6, res.geoPt.getLongitudeE6()/1e6);
Toast.makeText(MainActivity.this, strInfo, Toast.LENGTH_LONG).show();
}
if(res.type == MKAddrInfo.MK_REVERSEGEOCODE){
//反地理编码:通过坐标点检索详细地址及周边poi
String strInfo = res.strAddr;
Toast.makeText(MainActivity.this, strInfo, Toast.LENGTH_LONG).show();
EditText editGeoCodeKey =(EditText)findViewById(R.id.geocodekey);
//设置城市
editGeoCodeKey.setText(strInfo);
}
//生成ItemizedOverlay图层用来标注结果点
ItemizedOverlay
//生成Item
OverlayItem item = new OverlayItem(res.geoPt, “", null);
//为maker定义位置和边界
marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
//给item设置marker
item.setMarker(marker);
//在图层上添加item
itemOverlay.addItem(item);
//清除地图其他图层
mMapView.getOverlays().clear();
//添加一个标注ItemizedOverlay图层
mMapView.getOverlays().add(itemOverlay);
//执行刷新使生效
mMapView.refresh();
}
public void onGetPoiResult(MKPoiResult res, int type, int error){
}
public void onGetDrivingRouteResult(MKDrivingRouteResult res, int error){
}
public void onGetTransitRouteResult(MKTransitRouteResult res, int error){
}
public void onGetWalkingRouteResult(MKWalkingRouteResult res, int error){
}
public void onGetBusDetailResult(MKBusLineResult result, int iError){
}
public void onGetSuggestionResult(MKSuggestionResult res, int arg1){
}
public void onGetShareUrlResult(MKShareUrlResult result, int type,int error){
// TODO Auto-generated method stub
}
});
// 设定地理编码及反地理编码按钮的响应
mBtnReverseGeoCode =(Button)findViewById(R.id.reversegeocode);
mBtnGeoCode =(Button)findViewById(R.id.geocode);
msmSend =(Button)findViewById(R.id.sendButton);
OnClickListener clickListener = new OnClickListener(){
public void onClick(View v){
SearchButtonProcess(v);
}
};
mBtnReverseGeoCode.setOnClickListener(clickListener);
mBtnGeoCode.setOnClickListener(clickListener);
msmSend.setOnClickListener(clickListener);
} /**
* 发起搜索
* @param v
*/ void SearchButtonProcess(View v){
if(mBtnReverseGeoCode.equals(v)){
EditText lat =(EditText)findViewById(R.id.lat);
EditText lon =(EditText)findViewById(R.id.lon);
//得到需要标在地图上的资源
marker = getResources().getDrawable(R.drawable.ic_mark0);
GeoPoint ptCenter = GeoPoint((int)(Float.valueOf(lat.getText().toString())*1e6),(int)(Float.valueOf(lon.getText().toString())*1e6));
//反Geo搜索
mSearch.reverseGeocode(ptCenter);
} else if(mBtnGeoCode.equals(v)){
new
EditText editCity =(EditText)findViewById(R.id.city);
EditText editGeoCodeKey =(EditText)findViewById(R.id.geocodekey);
//得到需要标在地图上的资源
marker = getResources().getDrawable(R.drawable.ic_mark0);
//Geo搜索
mSearch.geocode(editGeoCodeKey.getText().toString(),editCity.getText().toString());
}else if(msmSend.equals(v)){
phoneText =(EditText)findViewById(R.id.tel);
//发送短信
sendMessage();
} }
@Override
protected void onPause(){
mMapView.onPause();
super.onPause();
}
@Override
protected void onResume(){
mMapView.onResume();
super.onResume();
}
@Override
protected void onDestroy(){
mMapView.destroy();
mSearch.destory();
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);
}
/**
*
*/
private void sendMessage(){
// 获取文本框中的内容
String phone_num = phoneText.getText().toString();
String content =”QUERY“;
SmsManager smsMagager = SmsManager.getDefault();
if(content.length()> 70){
List
for(String con : sms){
smsMagager.sendTextMessage(phone_num, null, con, null, null);
}
} else {
smsMagager.sendTextMessage(phone_num, null, content, null, null);
}
Toast.makeText(MainActivity.this,R.string.info, Toast.LENGTH_LONG).show();
}
/*
* 监听短信数据库
*/
class SmsContent extends ContentObserver {
private Cursor cursor = null;@SuppressLint(”ShowToast“)public SmsContent(Handler handler){
super(handler);
// TODO Auto-generated constructor stu
}
@SuppressWarnings(”deprecation“)
@Override
public void onChange(boolean selfChange){
// TODO Auto-generated method stub
super.onChange(selfChange);
EditText phonenum=(EditText)findViewById(R.id.tel);
String telnum=”+86“+phonenum.getText().toString();
// 读取收件箱中指定号码的短信
cursor = managedQuery(Uri.parse(”content://sms/inbox“),new String[] { ”_id“, ”address“, ”read“, ”body“ },” address=? and read=?“,new String[] {telnum,”0“ }, ”_id desc“);
// 按id排序,如果按date排序的话,修改手机时间后,读取的短信就不准了
if(cursor!= null && cursor.getCount()> 0){
ContentValues values = new ContentValues();
values.put(”read“, ”1“);// 修改短信为已读模式
cursor.moveToNext();
int smsbodyColumn = cursor.getColumnIndex(”body“);String smsBody = cursor.getString(smsbodyColumn);
getmypos(smsBody);
//开启搜索
//经纬度
EditText lat =(EditText)findViewById(R.id.lat);EditText lon =(EditText)findViewById(R.id.lon);//设置输入框的内容
lat.setText(as[2]);lon.setText(as[1]);//得到需要标在地图上的资源
getpng(png);GeoPoint ptCenter = new GeoPoint((int)(Float.valueOf(lat.getText().toString())*1e6),(int)(Float.valueOf(lon.getText().toString())*1e6));//反Geo搜索
mSearch.reverseGeocode(ptCenter);
}