Android进阶高手(四)终谈GPS

 

        终于讲到GPS了!现在的LBS如火如荼的发展,Foursquare更是日进千里!有很多圈里人说,创业团队如果想在Android方面创业,最好是开发基于地理位置的应用。可以把电子商务、SNS、Android智能设备完美的融合在一起。今天我们的主角就是GPS。

        在Android开发过程中,一直有人在问,怎么在地图上绘制文本或加载图片。今天我们就来实现这个功能,先基础后深入。慢慢的积累才能在GPS这块稳步的了解更多。废话不多说,直接上图,有图有真相嘛。呵呵,截图如下:

Android进阶高手(四)终谈GPS_第1张图片      Android进阶高手(四)终谈GPS_第2张图片

                                                (图1)                                                                                                      (图2)

图1:是运行程序后出现的界面;

图2:是单价天涯海角后出现的界面;

根据上面截图,我们来完成整个Demo的开发过程。

1、当然,首先我们的申请Google Map服务,至于怎么申请,网上有很多的参考资料或查看开发文档,这里我就不说废话。

2、下载Google API,可能有些童靴在安装Android SDK时,没有把GoogleAPI顺带安装了。由于开发Google Map应用需要基于google aip,所以这里我们就要安装这个。至于怎么安装,我这里提供两种方法:(1)、Window ->Android SDK android AVD Manager->Available Package--->出现Google APIs by Google Inc下载;(2)、直接在网上下载google_apis-8文件,之后将此文件存放在add-ons文件中,之后重启eclipse工具,再按照上面的就出现你想要的了。

3、好了,预前准备都做好之后,该真枪实战了。呵呵,首先新建一个项目,命名为ScenicDisplay。

4、编写布局文件,代码如下:

<?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" 
    android:padding="0px"
    android:layout_margin="0px">

    <TextView
        android:id="@+id/textview"
        android:layout_width="fill_parent"
        android:layout_height="50px"
        android:background="#F0FFFF"
        android:textColor="#0000CD"
        android:padding="8dp"
        android:text=""
        />
    <com.google.android.maps.MapView
        android:id="@+id/map"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:apiKey="这里的apiKey写上你自己申请的"
        android:clickable="true"/>
    <LinearLayout 
        android:id="@+id/zoom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:gravity="center_horizontal" />

</LinearLayout>

5、在drawable-mdpi文件夹中存放一张图片,也就是上图中显示的五角星,图片可以自己添加设置一张。

6、编写主程序Activity代码,如下:

package com.wyf.wpf;

import java.util.ArrayList;
import java.util.List;

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;

public class ScenicDisplayActivity extends MapActivity {
	// 声明变量
	private TextView textView;
	private MapView mapView;
	/*
	 * 控制地图移动、伸缩,以某个GPS坐标为中心,控制MapView中的View组件,管理Overlay提供View的基本功能。
	 */
	private MapController mapController;
	/*
	 * Overlay:此类是一种专门在Target中的选择图上用2D图像进行标记的类,可用于覆盖在地
	 * 图(MapView)表面的图层,可以把它当成一个画板(Canvas),在重叠的Overlay对象上
	 * 绘制线条、地标。它有两个子类为ItemizedOverlay类、MyLocationOverlay类
	 */
	// 声明图层
	private positionOverlay pOverlay;
	private MyLocationOverlay myLocationOverlay;
	// 声明菜单
	private static final int MENU_CC = Menu.FIRST;
	private static final int MENU_SUN = Menu.FIRST + 1;
	private static final int MENU_TYHJ = Menu.FIRST + 2;
	// 声明数组,用于存放经纬度
	private GeoPoint[] position;

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		textView = (TextView) findViewById(R.id.textview);
		mapView = (MapView) findViewById(R.id.map);
		// 通过MapView来取得MapController对象
		mapController = mapView.getController();
		//运用MapController类的setZoom方法控制地图缩放的尺度,数值越大,地图的细节就越详细
		mapController.setZoom(17);
		// 设置地图模式
		mapView.setTraffic(true);
		/*
		 * Map的zoom采用了built-in机制,可以通过setBuiltInZoomControls(boolean)
		 * 来设置是否在地图上显示zoom控件
		 */
		mapView.setBuiltInZoomControls(true);
		// 获取经纬度值
		getPosition();
		getView(mapView);
	}

	// 设置经纬度
	public void getPosition() {
		position = new GeoPoint[3];
		position[0] = new GeoPoint((int) (40.362642 * 1000000),
				(int) (116.019793 * 1000000));
		position[1] = new GeoPoint((int) (45.789361 * 1000000),
				(int) (126.600048 * 1000000));
		position[2] = new GeoPoint((int) (18.292023 * 1000000),
				(int) (109.347711 * 1000000));
	}

	// 创建菜单选项
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// TODO Auto-generated method stub
		menu.add(0, MENU_CC, 0, "长城八达岭");
		menu.add(0, MENU_SUN, 1, "太阳岛");
		menu.add(0, MENU_TYHJ, 2, "天涯海角");
		return super.onCreateOptionsMenu(menu);
	}

	// 监听菜单选项事件
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// TODO Auto-generated method stub
		switch (item.getItemId()) {
		case MENU_CC:
			mapController.animateTo(position[0]);
			showDialog("世界文化遗产、国家5A级景区、国家重点文物保护单位、"
					+ "国家重点风景名胜区、中国旅游胜地四十佳之首、全国文明旅游风景示范区。");
			break;
		case MENU_SUN:
			mapController.animateTo(position[1]);
			textView.setText("是国内最大的城市中心江曼滩湿地景观,周边栽植北方特有的菩提树之称的康段。");
			break;
		case MENU_TYHJ:
			mapController.animateTo(position[2]);
			textView.setText("有热带海滩花岗岩风景区、购物区和度假村组成集成热带海洋风光....");
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	/*
	 * 用于判断服务器是否显示远程信息,如驾车导航,是MapActivity类中必须实现的子类; 返回true则显示远程信息,否则不显示
	 */
	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}

	/*
	 * //该方法是将我们定义好的图层覆盖在MapView上1、得到MapView中的图层,增加的图标以及图标的位置
	 * 2、得到我们自定义的图层(myLocationOverlay、positionOverlay)并处理定位功能调用的动作
	 * 3、将我们得到的图层放到MapView地图中
	 */
	public void getView(MapView map) {
		// 得到MapView中的图层
		List<Overlay> overlays = mapView.getOverlays();
		// 增加图标
		Drawable drawable = getResources().getDrawable(R.drawable.star_big_on);
		// 设置图标的位置
		drawable.setBounds(-drawable.getMinimumWidth(),
				-drawable.getMinimumHeight(), 0, 0);
		/*
		 * myLocationOverlay对象调用其runOnFirstFix()
		 * 方法并传入runnable参数,在其run方法中,去定义每次更新时执行程序块中的动作
		 * 将MapView设置成一般地图试图模式、修改地图缩放成度和目标地点移动等动作
		 */
		myLocationOverlay = new MyLocationOverlay(this, mapView);
		myLocationOverlay.runOnFirstFix(new Runnable() {

			@Override
			public void run() {
				// TODO Auto-generated method stub
				mapView.setTraffic(true);
				mapController.setZoom(17);
				mapController.animateTo(myLocationOverlay.getMyLocation());
			}

		});
		overlays.add(myLocationOverlay);
		pOverlay = new positionOverlay(drawable);
		overlays.add(pOverlay);
	}

	@Override
	protected void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		myLocationOverlay.enableMyLocation();
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		myLocationOverlay.disableMyLocation();
	}

	// 对话框显示
	public void showDialog(String str) {
		new AlertDialog.Builder(ScenicDisplayActivity.this).setTitle("景点简介")
				.setMessage(str)
				.setNegativeButton("确定", new DialogInterface.OnClickListener() {

					@Override
					public void onClick(DialogInterface dialog, int which) {
						// TODO Auto-generated method stub
						dialog.dismiss();
					}
				}).show();
	}

	/*
	 * ItemizedOverlay:此类可以让我们在地图上添加多条信息,不同的信息可以添加到不同的
	 * 图层上,图层与图层之间可以重叠,就想我们在绘制游戏背景一样,最里面那层是背景层,接着可以绘制多个元素在外层,然后将外层重叠在背景层上。
	 */
	private class positionOverlay extends ItemizedOverlay<OverlayItem> {
		private final int mRadius = 5;
		// 定义一个列表、用于装我们所要规定的旅游风景区
		private List<OverlayItem> items = new ArrayList<OverlayItem>();

		// 在地图上添加图标
		public positionOverlay(Drawable drawable) {
			super(drawable);
			// TODO Auto-generated constructor stub
			items.add(new OverlayItem(position[0], "中国长城八达岭", "21度"));
			items.add(new OverlayItem(position[1], "中国首批A5", "16度"));
			items.add(new OverlayItem(position[2], "中国名旅", "32度"));
			populate();// 处理positionOverlay类之后所需要的动作
		}

		// 根据编号抓取对应的"OverlayItem"对象返回,创建出图标的实体
		@Override
		protected OverlayItem createItem(int i) {
			// TODO Auto-generated method stub
			return items.get(i);
		}

		// "size"返回这个图层告知总共包含了多少个图标
		@Override
		public int size() {
			// TODO Auto-generated method stub
			return items.size();
		}

		/*
		 * 该方法用于处理用户所单击的图标的业务处理,如果不实现其方法,用户单击到图标时就不会有任何特殊的反应
		 */
		@Override
		protected boolean onTap(int index) {
			// TODO Auto-generated method stub
			Toast.makeText(ScenicDisplayActivity.this,
					"今天的气温是" + items.get(index).getSnippet(),
					Toast.LENGTH_SHORT).show();
			return super.onTap(index);
		}

		/*
		 * 1、canvas:用来绘制的画布2、mapView:需要被标记的MapView
		 * 3、shadow:为true则需要绘制阴影图层,否则需要绘制内容图层
		 */
		@Override
		public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
				long when) {
			// TODO Auto-generated method stub
			/*
			 * Projection类代表了MapView上得视窗坐标与经纬度坐标的映射关系,用MapView
			 * 对象调用getProjection()就可以得到该地图的projection对象
			 */
			Projection projection = mapView.getProjection();
			for (int index = size() - 1; index >= 0; index--) {
				// 遍历,取得对应图标
				OverlayItem overlayItem = getItem(index);
				// 获取图标的标题
				String title = overlayItem.getTitle();
				/*
				 * //Projection对象调用toPixels()方法得到由风景点得 经纬度地理坐标转化为在地图上的投影位置
				 */
				Point point = projection.toPixels(overlayItem.getPoint(), null);
				// 坐标圆形
				RectF oval = new RectF(point.x - mRadius, point.y - mRadius,
						point.x + mRadius, point.y + mRadius);
				Paint paint = new Paint();
				paint.setColor(Color.CYAN);
				paint.setAntiAlias(true);
				paint.setFakeBoldText(true);
				// 红色圆形
				Paint backpaint = new Paint();
				backpaint.setColor(Color.RED);
				backpaint.setAntiAlias(true);
				RectF backRectF = new RectF(point.x + 40 + mRadius, point.y - 3
						* mRadius, point.x + 65, point.y + 2 * mRadius);
				// 文字设置
				Paint paintText = new Paint();
				paintText.setColor(Color.BLUE);
				paintText.setTextSize(25);

				canvas.drawOval(oval, paint);
				canvas.drawRoundRect(backRectF, 10, 10, backpaint);
				canvas.drawText(title, point.x, point.y, paintText);
			}
			return super.draw(canvas, mapView, shadow, when);
		}
	}

}

在程序中,注释已经很清楚了,在此就不多说了。

7、最后别忘记在AndroidManifest.xml文件中添加权限如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wyf.wpf"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".ScenicDisplayActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <uses-library android:name="com.google.android.maps" />
    </application>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="com.google.android.maps" />

</manifest>

8、结束


 

 

你可能感兴趣的:(android,Google,layout,Constructor,menu,encoding)