PPT - 建國科技大學

Download Report

Transcript PPT - 建國科技大學

經濟部工業局
Android智慧型手機程式設計實務應用班
Android Google Maps
建國科技大學 資管系
饒瑞佶
2012/4
Google Maps
Reference:
http://developer.android.com/resources/tutorials/views/hello-mapview.html
• 取得Google Map API
Step1:先進入JDK目錄
Google Maps
• 透過keytool.exe建立認證指紋
• 需要debug_keystore路徑
Google Maps
• debug_keystore路徑
Google Maps
• 輸入keytool –list –alias androiddebugkey –
keystore “C:\Documents and
Settings\Administrator\.android\debug.keystore”
–storepass android –keypass android
Google Maps
• 產生認證指紋
Google Maps
• 進入Google Map API Key申請頁面
• http://code.google.com/intl/zh-Tw/android/addons/google-apis/maps-api-signup.html
輸入認證指紋碼
Google Maps
• 進入Google Map API Key申請頁面
• http://code.google.com/intl/zh-Tw/android/addons/google-apis/maps-api-signup.html
Google Maps
• 產生出API金鑰
0O7bGO2vQxBc90bpYbJ8PnSjJapePPkrSGRvP3
A
加入main.xml
<com.google.android.maps.MapView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:apiKey="0O7bGO2vQxBc90bpYbJ8PnSj
JapePPkrSGRvP3A" />
Google Maps
main.xml
Google Maps
• 建立新專案: HelloMaps
沒有Google APIs target
Google Maps
• 如果沒有Google APIs target
• 請選擇Available packages進行安裝
Google Maps
• 安裝完Google APIs target畫面
Google Maps
• 建立新專案:
HelloMaps
顯示Google Maps地圖
加入
改成MapActivity
加入
Google Maps
• AVD也要對應具備Google APIs功能
Google Maps
• 增加 <uses-permission
android:name="android.permission.INTERNET" />
• 在 <application> 裡頭增加 <uses-library
android:name="com.google.android.maps" /> 資訊
Google Maps
在Google Maps上加標示
• 需要一個overlay class,做堆疊圖層之用
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.drawable.Drawable;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.OverlayItem;
MapsOverlay
public class MapsOverlay extends ItemizedOverlay<OverlayItem> {
private ArrayList<OverlayItem> mapOverlays = new ArrayList<OverlayItem>();
private Context context;
public MapsOverlay(Drawable defaultMarker) {
super(boundCenterBottom(defaultMarker));
}
public MapsOverlay(Drawable defaultMarker, Context context) {
this(defaultMarker);
this.context = context;
}
@Override
protected OverlayItem createItem(int i) {
return mapOverlays.get(i);
}
@Override
public int size() {
return mapOverlays.size();
}
@Override
protected boolean onTap(int index) {
OverlayItem item = mapOverlays.get(index);
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
dialog.setTitle(item.getTitle());
dialog.setMessage(item.getSnippet());
dialog.show();
return true;
}
public void addOverlay(OverlayItem overlay) {
mapOverlays.add(overlay);
this.populate();
}
}
Main.xml
決定地圖能不能互動
決定View顯示方式
需要與layout_width或
layout_height一起使用
加入這段來切換地圖種類
layout_weight
改變看看
改變看看
改變看看
改變看看
改變看看
改變看看
HelloMaps
給定一個座標(未來可以來自於GPS)
坐標
圖示
在給定座標上
加圖示
圖示按下時
顯示的資訊
切換成衛星圖
切換成標準地圖
試試改變圖示
地址轉座標
try {
inputaddress=(EditText)findViewById(R.id.editText1);
Geocoder geocoder = new Geocoder(Maps1Activity.this, Locale.getDefault());
List<Address> geoResults =
geocoder.getFromLocationName(inputaddress.getText().toString(), 5);
while (geoResults.size()==0) {
geoResults = geocoder.getFromLocationName(inputaddress.getText().toString(), 5);
}
if (geoResults.size()>0) {
Address addr = geoResults.get(0);
Double latitude = addr.getLatitude() * 1E6;
Double longitude = addr.getLongitude() * 1E6;
tv1.setText(latitude + "/" + longitude);
showlocation((int) (addr.getLatitude() * 1E6),(int) (addr.getLongitude() * 1E6));
}
} catch (Exception e) {
tv1.setText("convert error");
}
AVD多數執行有問題,
最好使用手機測試
1600 Amphitheatre Parkway, Mountain View,
CA
Android 2.2
輸入地址
轉換地址成
座標
座標
顯示座標點
不用註冊Google Maps API也可以
使用Intent
利用Intent 玩Google Maps
• 建立新專案:
IntentMaps
顯示Google Maps地圖
要取消
利用Intent 玩Google Maps
• AVD也要對應具備Google APIs功能
利用Intent 玩Google Maps
• 增加 <uses-permission
android:name="android.permission.INTERNET" />
利用Intent 玩Google Maps
更多Google Maps
– Google Maps
URI 格式:
<< 沒有小圖示
geo:latitude,longitude
geo:0,0?q=latitude,longitude
<< 出現圖示
geo:latitude,longitude?z=zoom
geo:0,0?q=my+street+address
geo:0,0?q=business+near+city
–
<< 目前沒作用
<< 出現有註冊的位置(my已取消)
Google Streetview
URI 格式:
google.streetview:cbll=lat,lng&cbp=1,yaw,,pitch,zoom&mz=mapZoom
Uri uri=Uri.parse("google.streetview:cbll=46.813812,-71.207378&cbp=1,99.56,,1,5.27&mz=21");
只支援美加地區
更多Google Maps
• 顯示地圖
Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
• 路徑規劃
Uri uri = Uri.parse("http://maps.google.com/maps?
f=d&saddr=startLat%20startLng&daddr=endLat%20endLng&hl=en");
Intent it = new Intent(Intent.ACTION_VIEW, uri);
startActivity(it);
//where startLat, startLng, endLat, endLng are a long with 6 decimals
like: 50.123456
GPS
AndroidManiFest.xml
建立一個新專案HelloGPS
• 需要開放以下權限
–
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"
></uses-permission>
–
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"></u
ses-permission>
偵測是否開啟GPS
//如果沒有開啟GPS--------------------LocationManager
status=(LocationManager)(this.getSystemService(Context.LOCATION_S
ERVICE));
if(status.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
status.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
}else{
// 到系統開啟GPS與WIFI服務的畫面
startActivity(new
Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
//--------------------如果沒有開啟GPS
Android GPS運作方式
• 取得LocationManager:判定是否有提供定
位服務(硬體GPS或WIFI)
• 建立LocationProvider,設定定位參數,並
同時透過LocationManager取得座標(硬體
軟體,GPS或是WiFi)
• 設定LocationManager的Listener事件,偵測
事件的改變
• MapController負責控制Google Maps
GPS訊號抓取主體
宣告
GPS訊號
擷取主體
沒有GPS
時觸發
mLocationManager =(LocationManager)(this.getSystemService(Context.LOCATION_SERVICE));
if(mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) ||
mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)){
啟動GPS
如果沒有啟動
使用GPS服務,
將跳至設定畫面
}else{
// 到達系統開啟GPS與WIFI服務的畫面
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
//--------------------如果沒有開啟GPS
/* Provider 初始化 */
要求GPS提供服務
getLocationPrivider();
/* 設定事件的Listener */
設定GPS監聽
mLocationManager.requestLocationUpdates(mLocationPrivider, 2000, 0, mLocationListener);
服務
if(mLocation!=null)
//第一次顯示
{
// 取得速度
如果有GPS訊號,
double speed=mLocation.getSpeed()/1000*60*60; //原單位是m/s
double altitude = mLocation.getAltitude();
顯示到畫面上
tv_show_gps.setText("緯度:" + formatgeo(mLocation.getLatitude()) + " 經度:" +
formatgeo(mLocation.getLongitude()) + " 海拔:" + altitude + " m 速度:" + formatspeed(speed) + "km/h");
}
TextView tv_show_gps;
private ProgressDialog MyDialog;
private LocationManager mLocationManager;
private String mLocationPrivider="";
private Location mLocation;
宣告物件
// 取得LocationProvider
public void getLocationPrivider()
{
Criteria mCriteria01 = new Criteria();
mCriteria01.setAccuracy(Criteria.ACCURACY_FINE);
mCriteria01.setAltitudeRequired(true); //需要高度
mCriteria01.setBearingRequired(false);
mCriteria01.setCostAllowed(true);
mCriteria01.setPowerRequirement(Criteria.POWER_LOW);
mLocationPrivider = mLocationManager.getBestProvider(mCriteria01, true);
mLocation = mLocationManager.getLastKnownLocation(mLocationPrivider);
}
// 偵測位置改變
public final LocationListener mLocationListener = new LocationListener()
{
public void onLocationChanged(Location location)
{
//如果記錄進行中,就畫路線並更新移動距離
// 取得速度
double speed=location.getSpeed()/1000*60*60; //原單位是m/s
double altitude = location.getAltitude();
tv_show_gps.setText("緯度:" + formatgeo(location.getLatitude()) + " 經度:" +
formatgeo(location.getLongitude()) + " 海拔:" + altitude + " m 速度:" + formatspeed(speed) +
"km/h");
MyDialog.dismiss(); //結束進度
}
public void onProviderDisabled(String provider)
{
}
public void onProviderEnabled(String provider)
{
}
public void onStatusChanged(String provider,int status,Bundle extras)
{
}
};
//-----------------偵測位置改變
// 按BACK按鍵時關閉程式
@Override
public void onBackPressed() {
android.os.Process.killProcess(android.os.Process.myPid());
HelloGPSActivity.this.finish();
}
// 產生定位中視窗
private void createCancelProgressDialog(String title, String message, String buttonText) {
MyDialog = new ProgressDialog(this);
MyDialog.setTitle(title);
MyDialog.setMessage(message);
MyDialog.setButton(buttonText, new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
// Use either finish() or return() to either close the activity or just the dialog
android.os.Process.killProcess(android.os.Process.myPid());
HelloGPSActivity.this.finish();
return;
}
});
MyDialog.show(); // 顯示進度
}
// format GPS座標的方法
public String formatgeo(double num)
{
NumberFormat formatter = new DecimalFormat("###.####");
String s=formatter.format(num);
return s;
}
// format speed的方法
public String formatspeed(double num)
{
NumberFormat formatter = new DecimalFormat("###.##");
String s=formatter.format(num);
return s;
}
透過ddms送出模擬GPS座標到AVD
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
GPS
• 取得GPS訊號後,將其顯示到Google Maps
上,移動時,該點會移動
– 抹除舊圖層,放上新的點
• 顯示成一個動態路徑
– 將新的點加入原有圖層中,保留所有的點
• 將GPS座標記錄到SQLite資料庫,之後可以
重新取回
取得GPS訊號後,將其顯示到
Google Maps上
onCreate與宣告
MapView物
件與圖層
MapView對
應到圖層
清除圖層
顯示座標點
gpsonmaps.xml
來自於Google
Maps認證頁
LocationListener
清除圖層
顯示座標點
showmaps函數
負責在圖層上顯示GPS座標點
private void showmaps(Location location) {
Drawable drawable=this.getResources().getDrawable(R.drawable.ic_launcher);
MapsOverlay itemizedOverlay=new MapsOverlay(drawable,this);
double geoLatitude = location.getLatitude()*1E6;
double geoLongitude = location.getLongitude()*1E6;
GeoPoint point=new GeoPoint((int) geoLatitude, (int) geoLongitude);
OverlayItem overlayitem=new OverlayItem(point,"Hello","I'm in Athens, Greece!");
itemizedOverlay.addOverlay(overlayitem);
mapOverlays.add(itemizedOverlay);
MapController mapcontroller=mapView.getController();
mapcontroller.animateTo(point);
mapcontroller.setZoom(18);
}
最後!記得Activity要改成MapActivity
取得GPS訊號後,將其顯示到
Google Maps上並畫出軌跡
從前個範例修改
產生MyOverLay類別
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
public class MyOverLay extends Overlay {
private GeoPoint gp1;
private GeoPoint gp2;
private int mRadius=10;
private int mode=0;
/* 建構子,傳入起點與終點的GeoPoint 與mode */
public MyOverLay(GeoPoint gp1,GeoPoint gp2,int mode)
{
this.gp1 = gp1;
this.gp2 = gp2;
this.mode = mode;
}
@Override
public boolean draw
(Canvas canvas, MapView mapView, boolean shadow, long when)
{
Projection projection = mapView.getProjection();
if (shadow == false)
{
/* 設定筆刷 */
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLUE); //點的顏色
Point point = new Point();
projection.toPixels(gp1, point);
/* mode=1:建立起點 */
if(mode==1)
{
/* 定義RectF 物件 */
RectF oval=new RectF(point.x - mRadius, point.y - mRadius,
point.x + mRadius, point.y + mRadius);
/* 繪製起點的圓形 */
canvas.drawOval(oval, paint);
}
/* mode=2:畫路線 */
else if(mode==2)
{
Point point2 = new Point();
projection.toPixels(gp2, point2);
paint.setColor(Color.BLACK); //中間路徑的顏色
paint.setStrokeWidth(5);
paint.setAlpha(120);
/* 畫線 */
canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
}
/* mode=3:建立終點 */
else if(mode==3)
{
/* 避免誤差,先畫最後一段的路線 */
Point point2 = new Point();
projection.toPixels(gp2, point2);
paint.setColor(Color.RED); //結束點的顏色
paint.setStrokeWidth(5);
paint.setAlpha(120);
canvas.drawLine(point.x, point.y, point2.x,point2.y, paint);
/* 定義RectF 物件 */
RectF oval=new RectF(point2.x - mRadius,point2.y - mRadius,
point2.x + mRadius,point2.y + mRadius);
/* 繪製終點的圓形 */
paint.setAlpha(255);
canvas.drawOval(oval, paint);
}
}
return super.draw(canvas, mapView, shadow, when);
}
}
變數
// GPS座標前後點
GeoPoint gp1;
GeoPoint gp2;
MapController mapcontroller;
boolean _run;
修改onCreate
btn_streetview.setOnClickListener(new Button.OnClickListener() //strat
{
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
try{
gp1=gp2;
resetOverlay();
_run = true;
refreshMapView();
setRoute(1); //起點
}catch(Exception e){
}
}
});
btn_satellitetview.setOnClickListener(new Button.OnClickListener() //stop
{
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
_run = false;
setRoute(3); //終點
refreshMapView();
}
});
/* 取得GeoPoint 的方法 */
private GeoPoint getGeoByLocation(Location location)
{
GeoPoint gp = null;
try
{
if (location != null)
{
double geoLatitude = location.getLatitude()*1E6;
double geoLongitude = location.getLongitude()*1E6;
gp = new GeoPoint((int) geoLatitude, (int) geoLongitude);
}
}catch(Exception e){
e.printStackTrace();
}
return gp;
}
/* 更新MapView 的方法 */
public void refreshMapView()
{
mapView.displayZoomControls(true);
MapController myMC = mapView.getController();
myMC.animateTo(gp2);
myMC.setZoom(18);
mapView.setSatellite(false); //不用衛星地圖
mapView.setClickable(true); //設定地圖可以被選取移動
}
/* 重設Overlay 的方法 */
private void resetOverlay()
{
List<Overlay> overlays = mapView.getOverlays();
overlays.clear();
}
/* 設定路線的方法 */
private void setRoute(int mode)
{
MyOverLay mOverlay = new MyOverLay(gp1,gp2,mode);
List<Overlay> overlays = mapView.getOverlays();
overlays.add(mOverlay);
}
修改LocationListener
修改LocationListener
if(_run && iflocated){
gp2=getGeoByLocation(location);;
setRoute(2); //畫線
refreshMapView();
gp1=gp2;
}else if(iflocated==false) {
new AlertDialog.Builder(GPSLine.this)
.setTitle("定位")
.setMessage("定位完成,可以開始使用!")
.setPositiveButton("確認",new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
})
.show();
iflocated=true;
MyDialog.dismiss();
}