Android开发教程天文台

By admin in 天文台 on 2019年1月26日

本文节选于机械工业出版社推出的《Android应用开发揭秘》一 书,作者为杨丰盛。本书内容全面,详细讲解了Android框架、Android组件、用户界面开发、游戏开发、数据存储、多媒体开发和网络开发等基础知 识,而且还深入阐述了传感器、语音识别、桌面组件开发、Android游戏引擎设计、Android应用优化、OpenGL等高级知识。另外,本书还全面 介绍了如何利用原生的C/C++(NDK)和Python、Lua等脚本语言(Android Scripting Environment)来开发Android应用,并以迭代的方式重现了各种常用的Android应用和经典Android游戏的开发全过程。

 

 

上面的内容囊括9.3 谷歌 Map和9.4 桌面组件四个部分:

9.3.1  Google Map概述

9.3.2  准备工作

9.3.3  Google Map API的使用

9.3.4  定位系统

9.4.1  快速情势

9.4.2  实时文件夹

9.4.3  Widget开发

第9章  Android特色开发

Android
是一个面向应用程序开发的增加平台,它抱有众多存有吸引力的用户界面元素、数据管理和网络采纳等名特优的作用。Android
还提供了许多颇具特点的接口。本章我们将各自介绍那个吸引开发者眼球的特征开发,首要不外乎:传感器系统(Sensor)、语音识别技术
(RecognizerIntent)、谷歌(Google)Map和用来开发桌面的插件(Widget)。通过本章的读书,读者将对Android有一个更深远的问询,可以付出出一些有特点、有新意的应用程序。

9.3  Google Map

提起谷歌(Google) Map(Google地图),大家一概想到其姊妹产品谷歌Earth(谷歌地球)。全新的免费地图服务让谷歌(Google)在二〇〇五年震惊了整套互联网界。此后,各大门户纷繁推出自己的地形图服务,不少山头还
和Google一样提供了二次开发的API。如今,基于地图服务的各样应用已如比比皆是般随处萌发了。当然,对于谷歌的Android系统的话,
地图肯定也是必需的特征。

9.3.1  Google Map概述

谷歌 Map是 Google公司提供的电子地图服务,包蕴一些详细的卫星照片。它能提供二种视图:一是矢量地图(传统地图),可提供政区和畅行以及商业新闻;二是不相同分辨率的卫星照
片(俯视地图,与谷歌 Earth
上的卫星照片基本一样);三是新兴增加的时势视图,可以用来突显地形和等高线。它的姐妹产品是谷歌Earth——一个桌面应用程序,在三维模型上提供街景和更多的卫星视图及GPS定位的听从。

谷歌集团于二〇〇四年十月收购了美国Keyhole集团,推出了
http://maps.google.com,令人耳目一新。但Google
并未就此止步,在二〇〇五年七月首推出了桌面工具谷歌Earth,把“地球”放到了种种人的桌面上,让你坐在电脑前,就足以在名川大山间漫步,在高堂大厦群中鸟瞰。

理所当然,随着谷歌(Google) Map和GoogleEarth的出生,也应运而生了无数尤其有意思的应用,比如上边七个独立的依照谷歌Earth和Google Maps的小游戏分外有创意,吸引了重重玩家。

如图9-5所示,大家得以在海内外其余地方竟然海底模拟开飞机依然潜水艇,来旅游整个社会风气,更加多游戏请参见http://www.sea-seek.com/。

天文台 1

图9-5  模拟飞行

如图9-6所示,大家可以在地球上其余地点开着自己喜欢的车奔跑,格外有趣的是,可以在微机面前开着车在投机周围以及了解的地点模拟驾驶。详细音信请参见http://geoquake.jp/en/
webgame/DrivingSimulatorGM/。

天文台 2

图9-6  模拟驾驶

 

看似的应用还有许多,那里大家只介绍那四款,有趣味的对象可以自己去摸索。现在GoogleMap已经被利用到无数无线电话上了,那越发便宜了豪门的生活。下边大家来探视手机上哪些利用谷歌(Google)Map,如图9-7所示。

天文台 3

图9-7 Google Map 手机版

它概括如下效果:

·我的岗位(测试版):“我的职分”在地形图上出示你的当前任务(经常在 1000
米范围以内)。尽管没有
GPS,你也可以规定自己的岗位。谷歌(谷歌(Google))手机地图还帮忙内置
GPS,也足以链接到蓝牙5.0 GPS
传感器,以便更准确地规定用户的职位。“我的地点”成效是经过辨认你附近有线发射塔的新闻播报而规定你的任务的。

·地图和卫星视图:谷歌(Google)手机地图向你提供所查看地区的地形图和卫星视图,其界面的行使感觉与你在台式机上相同。
可沿其中一个样子滚动,以查看地图上的愈来愈多内容;或使用飞快键进行缩放。

·商户列表:借助于 Google的本土搜索引擎,可以按名称(如“星巴克(Buck)”)或项目(如“咖啡”)搜索商家,查看公司的营业时间和评分,然后,只需点击一下即可拨通感兴趣的集团的对讲机。有了“我的职务”功用,甚至都不须要输入当前位置即可方便地找到附近的信用社。

·驾车路线:可以很有益于地收获驾车路线,其中会分晓地标明每一趟转弯。有了“我的任务”功能,甚至都不要求输入出发点。

·公互换乘:查看公交和客车线路,确定转车路线,制定你在大地 80
四个都市的出行安排。“公交流乘”功能近年来适用于HUAWEI、Windows Mobile、S60
和任何匡助 Java 的无绳电话机。

·路况新闻:Google地图中的公路会按照实时路况数据,以肉色、粉色或灰色呈现。

·收藏夹:为您常去的地点加上书签,以便能在地图上那一个有利于地回到到这个地点。

我们不要觉得这一个作用在手机上很难完毕,尤其是在大家要读书的Android平杜阿拉,要完毕这几个职能是卓殊简单的,只要求选取Android
Maps API(地图API)和Android Location
API(定位API)即可。上面大家将学习怎么着来行使那一个API开发协调的地形图应用。

9.3.2  准备干活

在Android
SDK?1.5预装的add-on中提供了一个Map增添库com.google.android.maps,利用它就足以给android应用程序加上
强大的地图成效了。那个库的岗位是“Android
SDK路径”\add-ons\google_apis-3\libs。需求表达的是,这些库并不是正统的Android
sdk的情节,可以友善从这个地方下载,并内置你的sdk中,那样就足以为您新建的选择或者已部分使用加上地图成效了。在使用Android
Map API之前,还亟需提请一个Android Map API Key。

1.申请Android Map API Key

为了能意得志满地申请Android Map API
Key,必要求预备谷歌的账号和系统的注明。一般谷歌(Google)发布Key都亟待谷歌的账号,谷歌(Google)的账号是通用的,Gmail的
账号就能够了(没有的话能够到http://www.google.com/去申请一个)。当一个应用程序发布时必须要证明书,证明书其实就是MD5。我
们那里不是揭橥,而只是为着测试,可以运用Debug版的证件。上面我们来读书怎么申请Android
Map API Key。

手续1:找到你的debug.keystore文件。

声明的貌似路径为:C:\Documents and Settings\近来用户\Local
Settings\Application Data\
Android\debug.keystore。当然我们利用Eclipse开发,便可以打开Eclipse选用Windows→Preference→Android→Build,其中Default debug
keystore的值便是debug.keystore的途径,如图9-8所示。

天文台 4

图9-8  debug.keystore文件的义务

步骤2:取得debug.keystore的MD5值。

率先在命令提示符下进入debug.keystore文件所在的路子,执行命令:keytool
-list -keystore
debug.keystore,这时可能会提醒您输入密码,那里输入默许的密码“android”,即可得到MD5值,如图9-9所示。

天文台 5

图9-9  取得debug.keystore的MD5值

步骤3:申请Android Map的API Key。

开辟浏览器,输入网址:http://code.google.com/intl/zh-CN/android/maps-api-
signup.html,登录谷歌(Google)账号,在谷歌(Google)的Android Map API
Key申请页面上输入步骤2取得的MD5认证指纹,选中“I have read and agree with
the terms and conditions”选项,如图9-10所示,按下“Generate API
Key”按钮,即可得到大家提请到的API Key。

天文台 6

图9-10  Android Map API Key申请页面

到这里我们便达成了Android Map API Key的提请,记下申请的Android Map API
Key值,在前边的应用程序中会用到它。下边大家还将开创一个基于GoogleAPIs的AVD。

2.开立基于谷歌(Google) APIs的AVD

在Eclipse中开拓AVD管理界面,在“Create
AVD”部分的Name处填写AVD的名字,在Target处拔取“谷歌(Google)APIs-1.5”,如图9-11所示,点击“Create AVD”按钮落成创制。

天文台 7

图9-11  创建AVD

3.创建基于谷歌 APIs的工程

此地必要小心的是,由于大家需求选拔谷歌(Google) APIs,所以在创设工程时,在Build
Target处须要选择谷歌APIs,如图9-12所示,其余选项和原先一样。当然,在运作工程时也就须求拔取我们恰好成立的根据GoogleAPIs的AVD来运转。

天文台 8

图9-12  创造基于谷歌 APIs的工程

到那边,我们着力形成了预备工作,上边我们将启幕攻读怎么着使用谷歌(Google)API来开发地图应用程序。 

9.3.3  Google Map API的使用

Android中定义了一个名为com.google.android.maps的包,其中包括了一密密麻麻用于在谷歌(Google)Map上呈现、控制和层叠音信的功能类,以下是该包中最关键的多少个类:

·MapActivity:这么些类是用来显示谷歌(Google)Map的Activity类,它必要两次三番底层网络。MapActivity是一个抽象类,任何想要展现MapView的activity都亟需派生自
MapActivity,并且在其派生类的onCreate()中,都要创设一个MapView实例。

·MapView:MapView是用来体现地图的View组件。它派生自android.view.ViewGroup。它必须和
MapActivity包容使用,而且不得不被MapActivity创设,那是因为MapView必要通过后台的线程来连接网络或者文件系统,而那么些线程
要由MapActivity来治本。

·MapController:MapController用于控制地图的位移、缩放等。

·Overlay:这是一个可突显于地图之上的可绘制的对象。

·GeoPoint:那是一个包涵经纬度地点的对象。

上边我们将采取com.google.android.maps包来落到实处一个地形图浏览程序(见本书所附代码:第9章\Examples_09_03)。

手续1:创设工程,注意要拔取的Build Target为“谷歌 APIs”。

步骤2:修改AndroidManifest.xml文件。

鉴于大家要选用谷歌 Map
API,所以必须先在AndroidManifest.xml中定义如下音信:<uses-library
android:name=”com.google.android.maps”/>,当然要从网络得到地图数据,还索要加上应用程序访问网络的权
限。代码如下:

     <uses-library android:name=”com.google.android.maps” />

步骤3:创建MapView。

要展示地图,须求成立一个MapView,在XML文件中的布局如代码清单9-3所示。其中android:apiKey的值便是咱们提请的Android
Map API Key。

     代码清单9-3  main.xml

     <?xml version=”1.0″ encoding=”utf-8″?> 

     <RelativeLayout
xmlns:android=”http://schemas.android.com/apk/res/android” 

         android:layout_width=”fill_parent” 

         android:layout_height=”fill_parent” 

         > 

     <com.google.android.maps.MapView

     android:id=”@+id/MapView01″

     android:layout_width=”fill_parent”

     android:layout_height=”fill_parent”

     android:apiKey=”0dYpmIXGIdwiVm-HEpzuUW2fjNYsFQ9EvYir1sg”/>

     </RelativeLayout> 

本来,能够在程序中经过如下代码创立MapView。

     MapView map = new MapView(this, “[Android Maps API Key]”);     

步骤4:实现MapActivity。

MapView必要由MapActivity来管理,所以程序部分应该继承自MapActivity类,必须贯彻isRouteDisplayed
方法。MapView提供了3种格局的地图,分别可以由此以下情势设置使用什么形式来显示地图。此外,可以经过
setBuiltInZoomControls方法设置地图是或不是接济缩放。

     //设置为直通情势

     //mMapView.setTraffic(true);

     //设置为卫星情势

     //mMapView.setSatellite(true); 

     //设置为街景形式

     //mMapView.setStreetView(false)   

步骤5:MapController的使用。

一经要设置地图突显的地点以及放大的倍数等,就须求利用MapController来控制地图。能够因而如下代码得到MapController对象:

     mMapController = mMapView.getController();   

要定位地方,要求构建一个GeoPoint来代表地点的经度和纬度,然后使用animateTo方法将地图定位到指定的GeoPoint上,代码如下:

     //设置源点为里约热内卢

     mGeoPoint=new
GeoPoint((int)(30.659259*1000000),(int)(104.065762*1000000));

     //定位到斯图加特

     mMapController.animateTo(mGeoPoint);    

步骤6:Overlay的使用。

万一急需在地形图上标爱他美(Aptamil)些图标文字等新闻,就需求运用Overlay。那里大家第一要将地图上的经度和纬度转换成显示器上其实的坐标,才能将新闻绘制
上去。Map API中提供了Projection.toPixels(GeoPoint in, Point
out)方法,能够将经度和纬度转换成屏幕上的坐标。首先需求贯彻Overlay中的draw方法才能在地图上绘制新闻,代码如下:

     class MyLocationOverlay extends Overlay

     {

     public boolean draw(Canvas canvas,MapView mapView,boolean
shadow,long when)

     {

     //…

     }

     }     

上边是出现说法运行效果,图9-13以交通情势显示地图,图9-14以卫星形式突显地图,它们都在屏幕上出示了一个图标,并标明了地点。

天文台 9               

   图9-13  交通方式地图

天文台 10                     

   图9-14  卫星情势地图

该示例突显了阿坝纳西族门巴族自治州区的地形图,标注了天府广场的大致地方,具体落到实处如代码清单9-4所示。

     代码清单9-4
 第9章\Examples_09_03\src\com\yarin\android\Examples_09_03\Activity01.java

     public class Activity01 extends MapActivity

     {

     private MapView mMapView;

     private MapController mMapController; 

     private GeoPoint mGeoPoint;

     public void onCreate(Bundle savedInstanceState)

     {

     super.onCreate(savedInstanceState);

     setContentView(R.layout.main);

     mMapView = (MapView) findViewById(R.id.MapView01);

     //设置为直通情势

     //mMapView.setTraffic(true);

     //设置为卫星方式

     mMapView.setSatellite(true); 

     //设置为街景格局

     //mMapView.setStreetView(false);

     //取得MapController对象(控制MapView)

     mMapController = mMapView.getController(); 

     mMapView.setEnabled(true);

     mMapView.setClickable(true);

     //设置地图协理缩放

     mMapView.setBuiltInZoomControls(true); 

     //设置源点为天津

     mGeoPoint=new
GeoPoint((int)(30.659259*1000000),(int)(104.065762*1000000));

     //定位到安特卫普

     mMapController.animateTo(mGeoPoint); 

     //设置倍数(1-21)

     mMapController.setZoom(12); 

     //添加Overlay,用于浮现标注音讯

             MyLocationOverlay myLocationOverlay = new
MyLocationOverlay();

             List<Overlay> list = mMapView.getOverlays();

             list.add(myLocationOverlay);

     }

     protected boolean isRouteDisplayed()

     {

     return false;

     }

     class MyLocationOverlay extends Overlay

     {

     public boolean draw(Canvas canvas,MapView mapView,boolean
shadow,long when)

     {

     super.draw(canvas, mapView, shadow);

     Paint paint = new Paint();

     Point myScreenCoords = new Point();

     // 将经纬度转换成实际屏幕坐标

     mapView.getProjection().toPixels(mGeoPoint,myScreenCoords);

     paint.setStrokeWidth(1);

     paint.setARGB(255, 255, 0, 0);

     paint.setStyle(Paint.Style.STROKE);

     Bitmap bmp = BitmapFactory.decodeResource(getResources(), 

     R.drawable.home);

     canvas.drawBitmap(bmp,myScreenCoords.x,myScreenCoords.y,paint);

     canvas.drawText(“天府广场”,myScreenCoords.x, myScreenCoords.y,

     paint);

     return true;

     }

     }

     }

9.3.4  定位系统

芸芸众生定位系统(Global Positioning
System,GPS)又称为环球卫星定位系统,是一个远距离圆型轨道卫星导航系统,它可以为地球表面的多方面所在(98%)提供精确的原则性、测速和高
精度的岁月标准。该体系由美国国防部研制和保安,可满足位于环球任哪个地方方或近地空间的枪杆子用户三番五次、精确地确定三维地点、三维运动和时间的必要。该种类蕴含太空中的24颗GPS卫星,地面上的1个主控站、3个数据注入站和5个监测站及作为用户端的GPS接收机。最少只需其中3颗卫星,就能高效确定用户端在
地球上所处的地点及海拔中度。所能连接到的卫星数越来越多,解码出来的职分就越精确。GPS广泛应用于部队、物流、地理、移动电话、卡片机、航空等世界,具
有尤其强劲的效应,主要不外乎:

·精确定时:广泛应用在天文台、通讯系统基站、电视机塞内加尔达喀尔。

·工程施工:道路、桥梁、隧道的动工中大量拔取GPS设备进行工程测量。

·勘探测绘:野外勘探及大埔县企划中都有用到。

·导航。

···武器导航:精确制导导弹、巡航导弹。

···车辆导航:车辆调度、监控系统。 

···船舶导航:远洋导航、港口/内河引水。 

···飞机导航:航线导航、进场着陆控制。 

···星际导航:卫星轨道定位。 

···个人导航:个人旅游及野外探险。 

·定位。

···车辆防盗系统。 

···手机、PDA、PPC等通讯移动装备防盗以及电子地图、定位系统。 

···小孩子及特殊人群的防走失系统。 

·精准农业:农机具导航、自动驾驶以及土地高精度平整。

Android
协理地理定位服务的API。该地理定位服务可以用来取得当前设施的地理地点,应用程序可以定时请求更新配备当前的地理定位消息。比如应用程序可以借助一个
Intent接收器来兑现如下效果:以经纬度和半径划定一个区域,当设备出入该区域时,发出提醒新闻,还足以和谷歌Map
API一起利用,达成越多的天职。关于地理定位系统的API全部坐落android.location包内,其中包括以下多少个第一的功效类:

·LocationManager:本类提供访问定位服务的作用,也提供获取最佳定位提供者的功力。此外,临近警报成效也足以依靠该类来兑现。

·LocationProvider:该类是平素提供者的抽象类。定位提供者具备周期性报告设备地理地点的意义。

·LocationListener:提供固定音信暴发变更时的回调功用。必须优先在一定管理器中登记监听器对象。

·Criteria:该类使得应用可以通过在LocationProvider中装置的性能来抉择适宜的原则性提供者。

·Geocoder:用于拍卖地理编码和反向地理编码的类。地理编码是指将地方或任何描述转变为经度和纬度,反向地理编码则是将经度和纬度转变为地
址或描述语言,其中包括了三个构造函数,须求传入经度和纬度的坐标。getFromLocation方法可以得到一组有关地方的数组。

要使用地理定位,首先需求获得LocationManager的实例,在Android中,得到LocationManager的绝无仅有办法是透过
getSystem瑟维斯(Service)(Service)()方法的调用。通过采纳LocationManager,我们可以取得一个地方提供者的列表。在一个实打实的手持设备
中,这一个列表包蕴了一部分GPS服务。我们也得以拔取更强大、更准确、不带有别的叠加服务的GPS。代码如下:

    
LocationManager?locationManager?=?(LocationManager)?getSystemService(Context.LOC-

     ATION_SERVICE);? 

得到LocationManager对象之后,大家还须求注册一个周期性的更新视图,代码如下:

    
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,1000,
0, 

     locationListener);    

里头首个参数是安装服务提供者,首个参数是周期,那里须要重点说贝拉米(Bellamy)下最终一个参数locationListener,它用来监听定位音讯的转移,所以大家不可能不兑现以下多少个艺术:

·onLocationChanged(Location
location):当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发。
  

·onProviderDisabled(String
provider):Provider禁用时触发此函数,比如GPS被关闭。

·onProviderEnabled(String
provider):Provider启用时触发此函数,比如GPS被打开。   

·onStatusChanged(String provider, int status, Bundle
extras):Provider的转态在可用、暂时不可用和无劳动多少个情景平昔切换时触发此函数。 

上边大家通过改变上一节的事例(本书所附代码:第9章\Examples_09_04)来已毕自动通过定位系统获取用户眼前的坐标,然后加载并突显地图,将坐标音讯浮现在一个TextView中,运行效果如图9-15所示。

天文台 11

图9-15 地图定位

要动用一定的API,首先需求在AndroidManifest.xml文件中添加其权力,具体代码如代码清单9-5所示。

     代码清单9-5  第9章\Examples_09_04\AndroidManifest.xml

     <?xml version=”1.0″ encoding=”utf-8″?>

     <manifest
xmlns:android=”http://schemas.android.com/apk/res/android

           package=”com.yarin.android.Examples_09_04″

           android:versionCode=”1″

           android:versionName=”1.0″>

         <application android:icon=”@drawable/icon”
android:label=”@string/app_name”>

     <uses-library android:name=”com.google.android.maps” />

             <activity android:name=”.Activity01″

                       android:label=”@string/app_name”>

                 <intent-filter>

                     <action
android:name=”android.intent.action.MAIN” />

                     <category
android:name=”android.intent.category.LAUNCHER” />

                 </intent-filter>

             </activity>

         </application>

     <uses-permission android:name=”android.permission.INTERNET”/>

          <uses-permission
android:name=”android.permission.ACCESS_COARSE_LOCATION”/>

          <uses-permission
android:name=”android.permission.ACCESS_FINE_LOCATION”/>

         <uses-sdk android:minSdkVersion=”5″ />

     </manifest>

鉴于大家在模拟器上测试,所以需求人工设置一个坐标。可以通过三种办法来设置一个模拟的坐标值。第一种格局是由此DDMS,大家可以在
Eclipse的ADT插件中应用那种艺术,只要开动Eclipse,选用“Window”->“Show
View”,打开“Emulator
Control”界面即可看到如下的安装窗口,我们可以手动照旧经过KML和GPX文件来安装一个坐标。如图9-16所示。

天文台 12

图9-16  设置彰显的坐标

另一种格局是采纳geo命令,我们须求telnet到本机的5554端口,然后在指令行下输入类似于geo
fix-121.45356 46.51119 4392
这样的下令,前面3个参数分别表示了经度、纬度和(可选的)海拔。设置之后在Android模拟器显示屏上便多出一个如图9-17所示的注脚,表示模拟了
GPS权限。

天文台 13

图9-17  GPS使用标志

现今我们可以利用地方管理器(LocationManager)和岗位提供者举行getFromLocation的调用。这一个点子重临本机当前位置的一个快照,这几个快照将以
Location对象形式提供。在手持设备中,我们可以收获当前义务的经度和纬度;调用getFromLocationName方法恐怕回到一个数额,表
示一个地点的称呼。该例中我们还创建了一个菜谱用来缩放地图,那时就使用地图控制器(MapController)的zoomIn和zoomOut方法来
放大和收缩视图,具体贯彻如代码清单9-6所示。

     代码清单9-6
 第9章\Examples_09_04\src\com\yarin\android\Examples_09_04\Activity01.java

     public class Activity01 extends MapActivity 

     {

         public MapController mapController;

         public MyLocationOverlay myPosition;

         public MapView myMapView;

         private static final int ZOOM_IN=Menu.FIRST; 

         private static final int ZOOM_OUT=Menu.FIRST+1;

     

     public void onCreate(Bundle savedInstanceState) {

             super.onCreate(savedInstanceState);

             setContentView(R.layout.main);

             //取得LocationManager实例

             LocationManager locationManager;

             String context=Context.LOCATION_SERVICE;

             locationManager=(LocationManager)getSystemService(context);

             myMapView=(MapView)findViewById(R.id.MapView01);

             //取得MapController实例,控制地图

             mapController=myMapView.getController();

             //设置显示情势

             myMapView.setSatellite(true);

             myMapView.setStreetView(true);

             //设置缩放控制,那里我们和好达成缩放菜单

             myMapView.displayZoomControls(false);   

             //设置使用MyLocationOverlay来绘图

             mapController.setZoom(17);

             myPosition=new MyLocationOverlay();

             List<Overlay> overlays=myMapView.getOverlays();

             overlays.add(myPosition);

             //设置Criteria(服务商)的信息

             Criteria criteria =new Criteria();

             //经度须要

             criteria.setAccuracy(Criteria.ACCURACY_FINE);

             criteria.setAltitudeRequired(false);

             criteria.setBearingRequired(false);

             criteria.setCostAllowed(false);

             criteria.setPowerRequirement(Criteria.POWER_LOW);

             //取得效果最好的criteria

             String provider=locationManager.getBestProvider(criteria,
true);

             //获得坐标相关的音信

             Location
location=locationManager.getLastKnownLocation(provider);

             //更新坐标

             updateWithNewLocation(location);

             //注册一个周期性的换代,3000ms更新一遍

             //locationListener用来监听定位音信的转移

             locationManager.requestLocationUpdates(provider, 3000,
0,locationListener);

         }

         private void updateWithNewLocation(Location location) 

         {

             String latLongString;

             TextView myLocationText =
(TextView)findViewById(R.id.TextView01);

             

             String addressString=”没有找到地点\n”;

             

             if(location!=null)

             {

                 //为绘制标志的类设置坐标

                 myPosition.setLocation(location);

                 //取得经度和纬度

                 Double geoLat=location.getLatitude()*1E6;

                 Double geoLng=location.getLongitude()*1E6;

                 //将其转移为int型

                 GeoPoint point=new
GeoPoint(geoLat.intValue(),geoLng.intValue());

                 //定位到指定坐标

                 mapController.animateTo(point);

                 double lat=location.getLatitude();

                 double lng=location.getLongitude();

                 latLongString=”经度:”+lat+”\n纬度:”+lng;

                 

                 double latitude=location.getLatitude();

                 double longitude=location.getLongitude();

                 //根据地理条件来规定编码

                 Geocoder gc=new Geocoder(this,Locale.getDefault());

                 try

                 {

                 //取得地点相关的局地消息、经度、纬度

                     List<Address>
addresses=gc.getFromLocation(latitude, longitude,1);

                     StringBuilder sb=new StringBuilder();

                     if(addresses.size()>0)

                     {

                         Address address=addresses.get(0);

                         for(int
i=0;i<address.getMaxAddressLineIndex();i++)

                            
sb.append(address.getAddressLine(i)).append(“\n”);

                             

                            
sb.append(address.getLocality()).append(“\n”);

                            
sb.append(address.getPostalCode()).append(“\n”);

                             sb.append(address.getCountryName());

                             addressString=sb.toString();

                     }

                 }catch(IOException e){}

             }

             else

             {

                 latLongString=”没有找到坐标.\n”;

             }

             //显示

            
myLocationText.setText(“你眼前的坐标如下:\n”+latLongString+”\n”+addressString);

         }

         private final LocationListener locationListener=new
LocationListener()

         {

         //当坐标改变时触发此函数

             public void onLocationChanged(Location location)

             {

             updateWithNewLocation(location);

             }

             //Provider禁用时触发此函数,比如GPS被关门 

             public void onProviderDisabled(String provider)

             {

             updateWithNewLocation(null);

             }

             //Provider启用时触发此函数,比如GPS被打开

             public void onProviderEnabled(String provider){}

            
//Provider的转态在可用、暂时不可用和无服务八个状态一直切换时触发此函数

             public void onStatusChanged(String provider,int
status,Bundle extras){}

         };

         protected boolean isRouteDisplayed()

     {

     return false;

     }

         //为应用程序添加菜单

         public boolean onCreateOptionsMenu(Menu menu)

     {

     super.onCreateOptionsMenu(menu);

     menu.add(0, ZOOM_IN, Menu.NONE, “放大”);

     menu.add(0, ZOOM_OUT, Menu.NONE, “缩小”);

     return true;

     }

         public boolean onOptionsItemSelected(MenuItem item)

     {

     super.onOptionsItemSelected(item);

     switch (item.getItemId())

     {

     case (ZOOM_IN):

     //放大

     mapController.zoomIn();

     return true;

     case (ZOOM_OUT):

     //缩小

     mapController.zoomOut();

     return true;

     }

     return true;

     }

     class MyLocationOverlay extends Overlay

     {

     Location mLocation;

     //在立异坐标时,设置该坐标,以便画图

     public void setLocation(Location location)

     {

     mLocation = location;

     }

     @Override

     public boolean draw(Canvas canvas,MapView mapView,boolean
shadow,long when)

     {

     super.draw(canvas, mapView, shadow);

     Paint paint = new Paint();

     Point myScreenCoords = new Point();

     // 将经纬度转换成实际屏幕坐标

     GeoPoint tmpGeoPoint = new GeoPoint((int)(mLocation.

     getLatitude()*1E6),(int)(mLocation.getLongitude()*1E6));

     mapView.getProjection().toPixels(tmpGeoPoint,myScreenCoords);

     paint.setStrokeWidth(1);

     paint.setARGB(255, 255, 0, 0);

     paint.setStyle(Paint.Style.STROKE);

     Bitmap bmp = BitmapFactory.decodeResource(getResources(), 

     R.drawable.home);

     canvas.drawBitmap(bmp,myScreenCoords.x,myScreenCoords.y,paint);

     canvas.drawText(“Here am I”,myScreenCoords.x,myScreenCoords.

     y, paint);

     return true;

     }

     }

     }

9.4  桌面组件

首先次开行Android模拟器时,能够看出在桌面上有过多图标,如图9-18所示的谷歌(Google)搜索框、时钟、联系人、浏览器等,点击这么些图标,
系统就会进行相应的先后,与PC操作系统桌面上的快速格局很像,可是它不完全是急速方式,还包罗了实时文件夹(Live
Folder)和桌面插件(Widget),那样既美观又方便用户操作。本节将学习那每一种桌面组件的开发,让我们团结的应用程序也能自在地停放到桌面
上。

天文台 14

图9-18 Android桌面组件

9.4.1  飞快格局

第一大家上学最基本的桌面组件快捷方式,它和PC上的火速格局一样,用于启动某一应用程序的某部组件(如Activity、瑟维斯(Service)等)。其
实要在桌面上添加一个快速形式很粗略,只要求长按桌面或者点击“Menu”按键(如图9-19所示),就可以弹出添加桌面组件的选项,如图9-20所
示,“Shortcuts”为添加飞快形式,“Widgets”为Widget开发的桌面插件,“Folders”为实时文件夹,进入相应的选项后即可添
加相应的桌面组件。

天文台 15

       图9-19  Menu菜单                                  图9-20
 添加桌面组件

本小节最主要介绍在应用程序中经过代码来将一个应用程序添加到图9-20的Shortcuts列表中,那里足够一个殡葬邮件的使用到连忙格局列表上去(参见本书所附代码:第9章\Examples_09_05)。

首先必要在Activity注册时添加一个Action为android.intent.action.CREATE_SHORTCUT的IntentFilter,如代码清单9-7所示,添加之后列表中就会油可是生该应用的图标和名字了。

     代码清单9-7  第9章\Examples_09_05\AndroidManifest.xml

     <?xml version=”1.0″ encoding=”utf-8″?>

     <manifest
xmlns:android=”http://schemas.android.com/apk/res/android

           package=”com.yarin.android.Examples_09_05″

           android:versionCode=”1″

           android:versionName=”1.0″>

         <application android:icon=”@drawable/icon”
android:label=”@string/app_name”>

             <activity android:name=”.Activity01″

                       android:label=”@string/app_name”>

                 <intent-filter>

                   <action android:name=”android.intent.action.MAIN”
/>

                   <category
android:name=”android.intent.category.LAUNCHER” />

     <action
android:name=”android.intent.action.CREATE_SHORTCUT”/> 

                 </intent-filter>

             </activity>

         </application>

         <uses-sdk android:minSdkVersion=”5″ />

     </manifest>   

接下去还要为快捷方式设置名字、图标、事件等属性。Intent.EXTRA_SHORTCUT_NAME对应火速形式的名
字;Intent.EXTRA_SHORTCUT_ICON_RESOURCE对应快速格局的图标;Intent.
EXTRA_SHORTCUT_INTENT对应神速格局执行的风云。须要验证的是,Android专门提供了
Intent.ShortcutIconResource.fromContext来成立快捷情势的图标,最终通过setResult来回到,构建一个神速格局,如代码清单9-8所示。

     代码清单9-8
 第9章\Examples_09_05\src\com\yarin\android\Examples_09_05\Activity01.java

     public class Activity01 extends Activity

     {

     public void onCreate(Bundle savedInstanceState)

     {

     super.onCreate(savedInstanceState);

     //要增加的快速格局的Intent

     Intent addShortcut; 

     //判断是还是不是要添加快捷形式

     if
(getIntent().getAction().equals(Intent.ACTION_CREATE_SHORTCUT))

     {

     addShortcut = new Intent(); 

     //设置快捷方式的名字

     addShortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME,”发送邮件”);

     //构建急忙方式中专门的图标

     Parcelable icon = Intent.ShortcutIconResource.fromContext

     (this,R.drawable.mail_edit);  

     //添加快捷格局图标

     addShortcut.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE,icon);

     //构建快速形式执行的Intent

     Intent mailto=new  Intent(Intent.ACTION_SENDTO, Uri.parse

     (“mailto:xxx@xxx.com” )); 

     //添加快速格局Intent

     addShortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT,mailto);  

     //正常

     setResult(RESULT_OK,addShortcut);  

     }

     else

     {

     //取消

     setResult(RESULT_CANCELED);  

     }

     //关闭

     finish();  

     }

     }   

今昔大家启动模拟器,就可以在Shortcuts列表中找到所添加的快速方式,将其添加到桌面,如图9-21所示。

天文台 16

图9-21  桌面急迅格局

9.4.2  实时文件夹

在Android 1.5中,Live Folders无疑是一个碰到关切的新成效。不难地说,Live
Folders就是一个查看你的手机中持有电子书、电子邮件、rss订阅、播放列表的飞快方式,并且这个内容是实时更新的。比如您不再须要单独打开电子邮
件软件查看邮件,打开通信录找联系人等。Live
Folders自带了列出装有联系人、所有有电话号码的调换人以及Starred联系人的成效,大家还足以应用Live
Folders API开发出越多的新式应用。

由于Live
Folders本身不存储任何音讯,都是以炫耀的办法查看其ContentProvider所指向的数目音讯,并得以自定义展现格式,所以当源数据暴发改
变后,Live
Folders可以实时更新呈现内容。那么在支付时,大家要确保所指定数量音讯URI的ContentProvider援助实时文件夹的询问。

其增进形式和添加迅速形式一样,只是在增选时要挑选“Folders”。本小节我们透过Live
Folders调用电话本中的信息,当点击其中一条音信时,便执行呼叫该联系人的动作(本书所附代码:第9章\
Examples_09_06)。

和开创飞速格局一样,大家需求在Activity注册时添加一个Action动作为android.intent.action.
CREATE_LIVE_FOLDER的IntentFilter。代码如下:

                 <intent-filter>

     <action android:name=
“android.intent.action.CREATE_LIVE_FOLDER” /> 

     <category android:name= “android.intent.category.DEFAULT” /> 

                 </intent-filter>

大家必要在程序中设置该实时文件夹的数据源、图标、名字的音讯。可以透过intent.setData方法来安装要读取的数据源,该例中咱们设置数
据源为“content://contacts/live_folders/people”,即联系人新闻。其余音讯的装置如表9-2所示。

表9-2  Live Folders的常用属性

天文台 17

在安装图标时,Android专门提供了Intent.ShortcutIconResource.fromContext来安装实时文件夹的图标。上面大家将实时文件夹添加到桌面(如图9-22所示),运行效果如图9-23所示。

天文台 18

图9-22 “电话本”实时文件夹                

天文台 19

图9-23  实时文件夹运行效果

上边必要在onCreate方法中校实时文件夹的相干新闻装入Intent对象,并通过setResult方法设置为结果Intent,最终调用finish方法甘休Activity,把结果再次回到给Home应用程序,以添加实时文件夹,如代码清单9-9所示。

     代码清单9-9
 第9章\Examples_09_06\src\com\yarin\android\Examples_09_06\Activity01.java

     public class Activity01 extends Activity

     {

     public void onCreate(Bundle savedInstanceState)

     {

     super.onCreate(savedInstanceState);

     // setContentView(R.layout.main);

     // 判断是还是不是制造实时文件夹

     if
(getIntent().getAction().equals(LiveFolders.ACTION_CREATE_LIVE_FOLDER))

     {

     Intent intent = new Intent();

     // 设置数据地址

     intent.setData(Uri.parse(“content://contacts/live_folders/

     people”));

     // 设置单击之后的风云,那里单击一个联络人后,呼叫

     intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_BASE_INTENT, 

     new Intent(Intent.ACTION_CALL,Contacts.People.CONTENT_URI));

     // 设置实时文件夹的名字

     intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME,”电话本”);

     // 设置举行文件夹的图标

     intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON, Intent.

     ShortcutIconResource.fromContext(this,R.drawable.contacts));

     // 设置显示形式为列表

     intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, 

     LiveFolders.DISPLAY_MODE_LIST);

     // 完成

     setResult(RESULT_OK, intent);

     }

     else

     {

     setResult(RESULT_CANCELED);

     }

     finish();

     }

     }

9.4.3  Widget开发

Widget是一种很小的应用程序,首要用作Web
2.0劳动或互联网内容的前端。Web设计人士与开发者可以采纳Widget来成立最受欢迎的互联网体验。在Android
1.5中加入了AppWidget
framework框架,开发者能够应用该框架开发Widget,这几个Widget可以拖到用户的桌面并且可以并行。Widget可以提供一个full-
featured
apps的预览,例如能够突显即将到来的日历事件,或者一首后台播放的歌曲的详细新闻。当Widget被拖到桌面上时,指定一个保存的空间来显示应用提供
的自定义内容。用户可以经过这么些Widget来和应用交互,例如暂停或切换歌曲。假如你有一个后台服务,可以根据你自己的Schedule更新您的
Widget,或者应用AppWidget framework提供一个机关的翻新机制。

各样Widget就是一个布罗德castReceiver,它们用XML
metadata来描述Widget的底细。AppWidget framework通过布罗德(Broad)cast
intents和Widget通讯,
Widget的换代使用RemoteViews来发送。RemoteViews被包裹成一个layout和特定内容来突显到桌面上。下边大家经过一个演示
来上学Widget开发(本书所附代码:第9章\Examples_09_07)。

率先须求在res\layout目录下创办桌面组件的布局文件appwidget_provider.xml,用来呈现桌面布局,那里大家成立一个TextView用来呈现一段文字,如代码清单9-10所示。

     代码清单9-10
 第9章\Examples_09_07\res\layout\appwidget_provider.xml

     <?xml version=”1.0″ encoding=”utf-8″?>

     <TextView
xmlns:android=”http://schemas.android.com/apk/res/android

         android:id=”@+id/appwidget_text” 

         android:textColor=”#ff000000″

         android:layout_width=”wrap_content”

         android:layout_height=”wrap_content”

     />

然后要求创造一个描述那个桌面组件属性的公文,存放到res\xml文件夹下,如代码清单9-11所示。

     代码清单9-11
 第9章\Examples_09_07\res\xmlappwidget_provider.xml

     <?xml version=”1.0″ encoding=”utf-8″?>

     <appwidget-provider
xmlns:android=”http://schemas.android.com/apk/res/android

         android:minWidth=”100dp”

         android:minHeight=”50dp”

         android:updatePeriodMillis=”86400000″

         android:initialLayout=”@layout/appwidget_provider”

        
android:configure=”com.yarin.android.Examples_09_07.Activity01″

         >

     </appwidget-provider>

中间android:minWidth和android:minHeight分别指定了桌面组件的很小宽度和纤维高度,其值可以依据期望的单元格数
量并使用前边介绍过的公式来测算(最小尺寸=(单元格数×74)?2),android:updatePeriodMillis是自动更新的光阴世隔,android:initialLayout是Widget的界面描述文件。Android:configure是可选的,假使你的Widget须要在开行前先启动一个Activity,则需求设定该项为你的Activity。那里我们须要先输入一段文字,然后展现在Widget上。

下一场要赤手空拳一个Widget,创设一个类,让其延续类AppWidgetProvider。在AppWidgetProvider中有多如牛毛艺术,包含onUpdate(周期更新时调用)、onDeleted(删除组件时调用)、onEnabled(当第三个零件创制时调用)、
onDisabled(当最终一个组件删除时调用),如代码清单9-12所示。

代码清单9-12
 第9章\Examples_09_07\src\com\yarin\android\Examples_09_07\ExampleAppWidget-
Provider.java

     public class ExampleAppWidgetProvider extends AppWidgetProvider

     {

     //周期更新时调用

     public void onUpdate(Context context,AppWidgetManager
appWidgetManager,int[] 

     appWidgetIds)

     {

     final int N = appWidgetIds.length;

     for (int i = 0; i < N; i++)

     {

     int appWidgetId = appWidgetIds[i];

     String titlePrefix=Activity01.loadTitlePref(context,appWidgetId);

     updateAppWidget(context, appWidgetManager, appWidgetId, 

     titlePrefix);

     }

     }

     //当桌面组件删除时调用

     public void onDeleted(Context context, int[] appWidgetIds)

     {

     //删除appWidget

     final int N = appWidgetIds.length;

     for (int i = 0; i < N; i++)

     {

     Activity01.deleteTitlePref(context, appWidgetIds[i]);

     }

     }

     //当AppWidgetProvider提供的首个零件创造时调用

     public void onEnabled(Context context)

天文台,     {

     PackageManager pm = context.getPackageManager();

     pm.setComponentEnabledSetting(new ComponentName(“com.yarin.android.

     Examples_09_07″, “.ExampleBroadcastReceiver”),

     PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 

     PackageManager.DONT_KILL_APP);

     }

     //当AppWidgetProvider提供的末梢一个零部件删除时调用

     public void onDisabled(Context context)

     {

     PackageManager pm = context.getPackageManager();

     pm.setComponentEnabledSetting(new ComponentName(“com.yarin.

     android.Examples_09_07″, “.ExampleBroadcastReceiver”),

     PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 

     PackageManager.DONT_KILL_APP);

     }

     //更新

     static void updateAppWidget(Context context, AppWidgetManager 

     appWidgetManager, int appWidgetId, String titlePrefix)

     {

     //构建RemoteViews对象来对桌面组件举办立异

     RemoteViews views = new RemoteViews(context.getPackageName(), 

     R.layout.appwidget_provider);

     //更新文本内容,指定布局的零部件

     views.setTextViewText(R.id.appwidget_text, titlePrefix);

     //将RemoteViews的更新传入AppWidget举办翻新

     appWidgetManager.updateAppWidget(appWidgetId, views);

     }

     }

中间,在updateAppWidget方法中大家构建了一个RemoteViews对象来对桌面组件举办翻新,通过
setTextViewText方法来更新一个文本的突显,然后通过updateAppWidget方法来将更新提需求AppWidget使其立异到桌
面。在onDisabled和onEnabled方法中大家用ComponentName来代表应用程序中某个组件的完全名字。

说到底,创立一个布罗德castReceiver类来接过更新的信息,在收受更新的音信之后就更新这几个桌面Widget组件,如代码清单9-13所示。

代码清单9-13
 第9章\Examples_09_07\src\com\yarin\android\Examples_09_07\ExampleBroadcast-
Receiver.java

     public class ExampleBroadcastReceiver extends BroadcastReceiver

     {

     public void onReceive(Context context, Intent intent)

     {

     //通过BroadcastReceiver来更新AppWidget

     String action = intent.getAction();

     if (action.equals(Intent.ACTION_TIMEZONE_CHANGED) ||
action.equals

     (Intent.ACTION_TIME_CHANGED))

     {

     AppWidgetManager gm = AppWidgetManager.getInstance(context);

     ArrayList<Integer> appWidgetIds = new
ArrayList<Integer>();

     ArrayList<String> texts = new ArrayList<String>();

     Activity01.loadAllTitlePrefs(context, appWidgetIds, texts);

     //更新所有AppWidget

     final int N = appWidgetIds.size();

     for (int i = 0; i < N; i++)

     {

     ExampleAppWidgetProvider.updateAppWidget(context, 

     gm, appWidgetIds.get(i), texts.get(i));

     }

     }

     }

     }

接下去,处理Android:configure指定的类,用来输入音讯,在此类中大家监听这么些按钮,当点击按钮之后,创建一个
AppWidgetManager实例,然后调用ExampleAppWidgetProvider.updateAppWidget方法来更新这个Widget,通过以下代码可以获得一个AppWidgetManager实例:

     AppWidgetManager appWidgetManager =
AppWidgetManager.getInstance(context);

专注,还亟需在AndroidManifest.xml中注册AppWidget、布罗德(Broad)castReceiver和用来输入新闻的Activity,如代码清单9-14所示。

     代码清单9-14  第9章\Examples_09_07\AndroidManifest.xml

     <?xml version=”1.0″ encoding=”utf-8″?>

     <manifest
xmlns:android=”http://schemas.android.com/apk/res/android

           package=”com.yarin.android.Examples_09_07″

           android:versionCode=”1″

           android:versionName=”1.0″>

         <application android:icon=”@drawable/icon”
android:label=”@string/app_name”>

             <receiver android:name=”.ExampleAppWidgetProvider”>

                 <meta-data android:name=”android.appwidget.provider”

                         android:resource=”@xml/appwidget_provider”
/>

                 <intent-filter>

                     <action
android:name=”android.appwidget.action.APPWIDGET_UPDATE” />

                 </intent-filter>

             </receiver>

             <activity android:name=”.Activity01″>

                 <intent-filter>

                     <action
android:name=”android.appwidget.action.APPWIDGET_CONFIGURE” />

                 </intent-filter>

             </activity>

             <receiver android:name=”.ExampleBroadcastReceiver”
android:enabled=”false”>

                 <intent-filter>

                     <action
android:name=”android.intent.ACTION_TIMEZONE_CHANGED” />

                     <action
android:name=”android.intent.ACTION_TIME” />

                 </intent-filter>

             </receiver>

         </application>

         <uses-sdk android:minSdkVersion=”5″ />

     </manifest>

上面将该Widget添加到桌面上,和添加疾速格局一样,如图9-24所示,然后输入要出示的文字,如图9-25所示,点击“确定”按钮之后,桌面即突显我们输入的新闻,如图9-26所示。

天文台 20             

图9-24  添加Widget到桌面    

天文台 21

图9-25  输入要突显的音讯          

天文台 22

图9-26  桌面展现Widget

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 亚洲必赢手机官网 版权所有