第一篇:Android地圖和定位學(xué)習(xí)總結(jié)
Android地圖和定位學(xué)習(xí)總結(jié)
首屆 Google 暑期大學(xué)生博客分享大賽——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對象是如何創(chuàng)建的? LocationManager
locMan=(LocationManager)getSystemService(Context.LOCATION_SERVICE);//LocationManager對象只能這么創(chuàng)建,不能用new Locationlocation=locMan.getLastKnownLocation(LocationManager.GPS_PROVIDER);if(location==null){
location=locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);} //注意要為應(yīng)用程序添加使用權(quán)限
自然是獲取最新的地理位置信息,那LocationManager.GPS_PROVIDER和LocationManager.NETWORK_PROVIDER有什么區(qū)別呢?俺也不是學(xué)通信的,對這個不了解,在網(wǎng)上看到有人想“在室外有GPS定位,在室內(nèi)想用Wifi或基站定位”。
除了直接使用LocationManager提供的靜態(tài)Provider(如GPS_PROVIDER和NETWORK_PROVIDER等)外,還可以使用我們自己創(chuàng)建的LocationProvider對象。創(chuàng)建LocationProvider對象一般要先創(chuàng)建Criteria對象,來設(shè)置我們的LocationProvider要滿足什么樣的標準 Criteria myCri=new Criteria();myCri.setAccuracy(Criteria.ACCURACY_FINE);//精確度 myCri.setAltitudeRequired(false);//海拔不需要
myCri.setBearingRequired(false);//Bearing是“軸承”的意思,此處可理解為地軸線之類的東西,總之Bearing Information是一種地理位置信息的描述 myCri.setCostAllowed(true);//允許產(chǎn)生現(xiàn)金消費
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();//獲取經(jīng)度
我想知道當前位置描述(比如“武漢華中科技大學(xué)”而不是一個經(jīng)緯值)呢?這就要使用GeoCoder創(chuàng)建一個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.(返回給定經(jīng)緯值附近的一個Address)既然是“附近”那實際編碼時我們沒必要把經(jīng)緯值給的那么精確,而取一個近似的整數(shù),像這樣: /*自經(jīng)緯度取得地址,可能有多行地址*/ 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.反過來我們可以輸入地址信息獲取經(jīng)緯值
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實現(xiàn)短信接收定位
工程文件結(jié)構(gòu):
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;}
// 常用事件監(jiān)聽,用來處理通常的網(wǎng)絡(luò)錯誤,授權(quán)驗證錯誤等
static class MyGeneralListener implements MKGeneralListener {
public void onGetNetworkState(int iError){
if(iError == MKEvent.ERROR_NETWORK_CONNECT){
Toast.makeText(DemoApplication.getInstance().getApplicationContext(), “您的網(wǎng)絡(luò)出錯啦!”,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(),“請輸入正確的授權(quán)Key,并檢查您的網(wǎng)絡(luò)連接是否正常!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相關(guān)
Button mBtnReverseGeoCode = null;// 將坐標反編碼為地址
Button mBtnGeoCode = null;// 將地址編碼為坐標
Button msmSend =null;//短信發(fā)送按鈕
//地圖相關(guān)
MapView mMapView = null;// 地圖View
//搜索相關(guān)
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);
/*
* 注冊短信變化事件監(jiān)聽
*/
SmsContent content = new SmsContent(new Handler());
//注冊短信變化監(jiān)聽
this.getContentResolver().registerContentObserver(Uri.parse(“content://sms/”), true, content);
//注冊短信變化監(jiān)聽
/**
* 使用地圖sdk前需先初始化BMapManager.* BMapManager是全局的,可為多個MapView共用,它需要地圖模塊創(chuàng)建前創(chuàng)建,* 并在地圖地圖模塊銷毀后銷毀,只要還有地圖模塊在使用,BMapManager就不應(yīng)該銷毀
*/
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);
// 初始化搜索模塊,注冊事件監(jiān)聽
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 經(jīng)度:%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);
//設(shè)置城市
editGeoCodeKey.setText(strInfo);
}
//生成ItemizedOverlay圖層用來標注結(jié)果點
ItemizedOverlay
//生成Item
OverlayItem item = new OverlayItem(res.geoPt, “", null);
//為maker定義位置和邊界
marker.setBounds(0, 0, marker.getIntrinsicWidth(), marker.getIntrinsicHeight());
//給item設(shè)置marker
item.setMarker(marker);
//在圖層上添加item
itemOverlay.addItem(item);
//清除地圖其他圖層
mMapView.getOverlays().clear();
//添加一個標注ItemizedOverlay圖層
mMapView.getOverlays().add(itemOverlay);
//執(zhí)行刷新使生效
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
}
});
// 設(shè)定地理編碼及反地理編碼按鈕的響應(yīng)
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);
} /**
* 發(fā)起搜索
* @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);
//發(fā)送短信
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(){
// 獲取文本框中的內(nèi)容
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();
}
/*
* 監(jiān)聽短信數(shù)據(jù)庫
*/
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);
//開啟搜索
//經(jīng)緯度
EditText lat =(EditText)findViewById(R.id.lat);EditText lon =(EditText)findViewById(R.id.lon);//設(shè)置輸入框的內(nèi)容
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);
}
// 在用managedQuery的時候,不能主動調(diào)用close()方法,否則在 android:layout_height=”match_parent“ tools:context=”.MainActivity“ > android:id=”@+id/bmapView“ android:layout_width=”fill_parent“ android:layout_height=”fill_parent“ android:clickable=”true“ /> android:id=”@+id/lat“ android:layout_width=”125dp“ android:layout_height=”wrap_content“ android:layout_alignParentLeft=”true“ android:layout_alignParentTop=”true“ android:ems=”10“ android:text=”39.904965“ />