十、定位服务
在本章中,我们将学习如何使用谷歌地图片段向我们的应用添加地图视图。我们将在地图上添加标记,用于指出感兴趣的位置。
为了做到这一点,我们还将讨论如何在谷歌开发者控制台中创建一个项目,并设置我们的应用使用谷歌游戏服务软件开发工具包,这是在任何安卓应用中使用谷歌服务所必需的。
每个工作机会在解析中都有一个位置字段;基于此,我们将在地图上显示标记。
- 配置项目
- 获取谷歌地图应用编程接口密钥
- 配置
AndroidManifest.xml
- 添加地图
- 为可视寻呼机创建片段
- 实现地图片段
- 添加标记
- 从分析中检索数据
- 为每个位置显示一个标记
- 添加标题
配置项目
为了让我们使用谷歌游戏服务应用编程接口,我们需要用谷歌游戏服务软件开发工具包来设置我们的项目。如果你还没有安装这个,去安卓软件开发工具包管理器,获取谷歌游戏服务软件开发工具包。
既然我们的应用使用了谷歌游戏服务,要测试该应用,您必须确保在以下任一平台上运行该应用:
- 安卓 2.3 或更高版本的安卓设备有谷歌 Play 商店(推荐)。
-
An emulator that has Google Play Services set up. If you use Genymotion, Google Play services will not be installed by default:
我们需要让谷歌游戏服务应用接口对我们的应用可用。
打开应用的build.gradle
文件,在依赖项下添加play-services
库。添加build.gradle
文件的行应该类似于这样:
compile 'com.google.android.gms:play-services:7.8.0'
确保您将此更改为最新版本的play-services
,并在新版本发布时进行更新。
保存文件,点击将项目与渐变文件同步。
获取 API 密钥
为了使用谷歌地图应用编程接口,我们需要在谷歌开发者控制台注册我们的项目,并接收一个应用编程接口密钥,然后我们将把它添加到我们的应用中。
首先,我们需要获得我们独特应用的 SHA-1 指纹。我们可以从调试证书或发布证书获得此信息。
- 调试构建完成后,会自动创建调试 证书。此证书只能用于当前正在测试的应用。不要使用调试证书发布应用。
- 发布版本 证书是在发布构建完成时制作的。也可以使用键工具程序创建证书。该证书必须在应用准备发布到 Play Store 时使用。
显示调试证书指纹
- 找到名为
debug.keystore
的调试密钥库文件。该文件通常与安卓虚拟设备文件位于同一目录:- OS X 和 Linux :
~/.android/
- Windows Vista 和 Windows 7 :
C:\Users\your_user_name\.android\
- OS X 和 Linux :
- 要显示 SHA-1 指纹,请打开终端或命令提示符窗口,并输入以下内容:
- OS X 和 Linux :我们使用
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
命令。 - Windows Vista 和 Windows 7 :我们使用
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
命令。
- OS X 和 Linux :我们使用
输入命令后,按回车键,会看到类似如下的输出:
Alias name: androiddebugkey
Creation date: Dec 16, 2014
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Android Debug, O=Android, C=US
Issuer: CN=Android Debug, O=Android, C=US
Serial number: 32f30c87
Valid from: Tue Dec 16 11:35:40 CAT 2014 until: Thu Dec 08 11:35:40 CAT 2044
Certificate fingerprints:
MD5: 7E:06:3D:45:D7:1D:48:FE:96:88:18:20:0F:09:B8:2A
SHA1: BD:24:B2:7C:DA:67:E5:80:78:1D:75:8C:C6:66:B3:D0:63:3E:EE:84
SHA256: E4:8C:BD:4A:24:CD:55:5C:0E:7A:1E:B7:FC:A3:9E:60:28:FB:F7:20:C6:C0:E9:1A:C8:13:29:A6:F2:10:42:DB
Signature algorithm name: SHA256withRSA
Version: 3
创建谷歌开发者控制台项目
去https://console.developers.google.com/project创建一个账户,如果你还没有这样做的话。首先,用你想要的名字创建一个新项目。创建项目后,请执行以下步骤:
-
In the left sidebar, click on APIs & auth and then select the APIs option:
-
选择谷歌地图安卓 API 并启用。
- 打开凭证,点击【新建键】。
-
选择安卓键,输入您的 SHA-1 指纹,后跟您项目的包名,用分号隔开,如下所示:
java BD:24:B2:7C:DA:67:E5:80:78:1D:75:8C:C6:66:B3:D0:63:3E:EE:84;com.packtpub.masteringandroidapp
-
Once you complete this, you will be able to view the credentials as in the following screenshot:
配置 AndroidManifest.xml
现在我们已经有了安卓应用的 API 密钥,我们需要将其添加到我们的AndroidManifest.xml
文件中。
打开您的AndroidManifest.xml
文件,在<application>
元素中添加以下代码作为子元素:
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="API_KEY"/>
将value
属性中的API_KEY
替换为谷歌开发者控制台上给出的 API 键。
我们还需要给我们的AndroidManifest
增加一些其他的设置。按如下方式设置谷歌游戏服务版本:
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
按如下方式设置所需权限:
INTERNET
:此权限用于从谷歌地图服务器下载地图数据。ACCESS_NETWORK_STATE
:这将允许 API 检查连接的状态,以确定它是否能够下载数据。WRITE_EXTERNAL_STORAGE
:这将允许 API 缓存地图数据。ACCESS_COARSE_LOCATION
:这让 API 可以使用 Wi-Fi 或移动数据检索设备的位置。-
ACCESS_FINE_LOCATION
:这将给出比ACCESS_COARSE_LOCATION
更精确的位置,它还将使用 GPS 以及 Wi-Fi 或移动数据。看看下面的代码:java <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
你还需要设置你的 OpenGL ES。地图应用编程接口使用 OpenGL ES 渲染地图,因此需要安装它才能显示地图。要将要求通知其他服务,并防止不支持 OpenGL 的设备在谷歌 Play 商店显示您的应用,请在您的AndroidManifest.xml
文件中添加以下内容作为<manifest>
的子级:
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
您当前的AndroidManifest.xml
文件应该类似于以下代码:
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.packtpub.masteringandroidapp">
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application android:name=".MAApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme">
<activity android:name=".SplashActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity" android:label="@string/title_activity_main" />
<activity android:name=".OfferDetailActivity" android:label="@string/title_activity_offer_detail" />
<provider android:name=".MAAProvider" android:authorities="com.packtpub.masteringandroidapp.MAAProvider" />
<meta-data android:name="com.google.android.geo.API_KEY" android:value="AIzaSyC9o7cLdk_MIX_aQhaOLvoqYywK61bN0PQ" />
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
</application>
</manifest>
添加地图
现在我们的应用已经配置为使用地图服务,我们可以开始讨论如何向我们的应用添加可视化地图。对于地图,我们将创建另一个片段,它将被加载到ViewPager
的第二页。
显示谷歌地图有两种方法;无论是MapFragment
还是MapView
对象都可以表示它。
添加片段
在我们的fragments
目录中创建新的 Java 类,名称为MyMapFragment
。班级应该扩展Fragment
类型。然后,覆盖OnCreateView
方法,让它返回fragment_my_map
的膨胀视图:
package com.packtpub.masteringandroidapp.fragments;
import …
/**
* Created by Unathi on 7/29/2015.
*/
public class MyMapFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_map, container, false);
return view;
}
}
接下来,为片段创建布局文件,并将其命名为fragment_my_map
。将布局的根元素设置为FrameLayout
。我们将暂时把TextView
添加到我们的布局中,只是为了验证它是否有效。fragment_my_map.xml
文件的代码应该类似如下:
<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="This is a TextView" android:layout_gravity="center" android:textSize="25dp" />
</FrameLayout>
将我们的片段添加到应用的最后一步是编辑MyPagerAdapter.java
文件,将其显示为第二页。为此,请更改getItem
方法中的第二种情况以返回MyMapFragment
的实例,并更改getPageTitle
方法中的第二种情况下的页面标题以返回MAP
:
@Override
public Fragment getItem(int i) {
switch (i) {
case 0 :
return new ListFragment();
case 1 :
return new MyMapFragment();
case 2 :
return new SettingsFragment();
default:
return null;
}
}
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0 :
return "LIST";
case 1 :
return "MAP";
case 2 :
return "SETTINGS";
default:
return null;
}
}
现在,当你运行该应用时,ViewPager
的第二页应该被我们的新片段替换。
实现映射片段
我们现在将使用在我们的应用上显示地图。我们可以通过添加带有com.google.android.gms.maps.MapFragment
的android:name
的<fragment>
布局来做到这一点。这样做会自动将MapFragment
添加到activity
:
以下是fragment_my_map.xml
的代码:
<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent">
<fragment android:name="com.google.android.gms.maps.MapFragment" android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" />
</FrameLayout>
接下来,为了能够处理我们添加到布局中的MapFragment
,我们需要使用从getChildFragmentManager
到findFragmentById
的FragmentManager
。这将在OnCreateView
方法中完成:
FragmentManager fm = getChildFragmentManager();
mapFragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
我们将把我们的片段分配给SupportMapFragment
而不仅仅是MapFragment
,这样应用就可以支持低于 12 的安卓应用编程接口级别。使用以下代码:
以下是MyMapFragment.java
的代码:
public class MyMapFragment extends Fragment{
private SupportMapFragment mapFragment;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_map, container, false);
FragmentManager fm = getChildFragmentManager();
mapFragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
return view;
}
}
现在,当我们运行该应用时,地图将显示在屏幕上。
添加标记
谷歌地图现在是可见的,但它还没有为用户显示任何有用的数据。为此,我们将添加地图标记来指示用户的兴趣点。这些将是不同工作机会的位置,我们将从我们的 Parse 数据库下载。
我们还将学习如何将用于在地图上标记点的图标更改为自定义图像,以及在标记上设置标题。这将使我们的应用看起来更加有趣和信息丰富。
从解析中检索数据
在我们可以显示我们所有的标记之前,我们需要从 Parse 下载所有必要的数据。
在MyMapFragment.java
中,我们将使用ParseQuery
检索位置列表,并在显示之前使用该列表获取每个工作机会的相关信息。请执行以下步骤:
- 创建名为
GoogleMap
类型的googleMap
的私有成员变量,并覆盖onResume()
方法。 -
在
onResume()
中,检查googleMap
是否为空;如果是,这意味着我们还没有向地图的当前实例添加标记。如果googleMap
是空的,从MapFragment
分配地图,我们已经创建了。这是使用getMap()
:```java if (googleMap == null) {
googleMap = MapFragment.getMap();
} ```
完成的 * 创建一个
ParseQuery
,它将检索我们的解析数据库的JobOffer
表的所有数据。将findInBackground()
功能与FindCallback
配合使用,这样我们可以只在数据全部下载后才开始处理数据。使用以下代码:```java ParseQuery query = ParseQuery.getQuery("JobOffer"); query.findInBackground(new FindCallback() { @Override public void done(List list, ParseException e) {
} }); ```
显示每个位置的标记
现在,我们将遍历从 Parse 收到的工作邀请列表,并使用addMarker()
给googleMap
添加一个标记。请执行以下步骤:
-
当
findInBackground
完成后,创建一个ParseGeoPoint
变量和一个循环,循环将迭代列表中的每个项目。我们将使用ParseGeoPoint
变量来存储解析数据库中的坐标:```java ParseGeoPoint geoPoint = new ParseGeoPoint();
for(int i =0;i<list.size();i++){
} ```
-
在循环中,从列表中获取
GeoPoint
数据,并将其保存到我们的ParseGeoPoint
变量:java geoPoint = list.get(i).getParseGeoPoint("coordinates");
-
最后,在每次迭代中用
addMarker()
:java googleMap.addMarker(new MarkerOptions() .position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude())));
给
googleMap
添加一个标记
您的 MyMapFragment.java
文件应该类似于以下内容:
public class MyMapFragment extends Fragment{
private SupportMapFragment mapFragment;
private GoogleMap googleMap;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_map, container, false);
FragmentManager fm = getChildFragmentManager();
mapFragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
fm.beginTransaction().add(R.id.map, mapFragment).commit();
}
return view;
}
@Override
public void onResume() {
super.onResume();
if (googleMap == null) {
googleMap = mapFragment.getMap();
ParseQuery<JobOffer> query = ParseQuery.getQuery("JobOffer");
query.findInBackground(new FindCallback<JobOffer>() {
@Override
public void done(List<JobOffer> list, ParseException e) {
ParseGeoPoint geoPoint;
for(int i =0;i<list.size();i++){
geoPoint = list.get(i).getParseGeoPoint("coordinates");
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude())));
}
}
});
}
}
}
这些标记现在应该在应用上可见:
给标记添加标题
在地图上有一个标记的用处不仅仅是显示一个点,也是给用户一个简单易懂的方法来获取这个位置的信息。我们将通过在点击标记时在标记上显示标题来做到这一点。
这可以通过简单地将.title(string)
添加到我们的addMarker()
方法中来实现:
googleMap.addMarker(new MarkerOptions()
.position(new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude()))
.title(list.get(i).getTitle()));
我们现在有了一个功能齐全的地图显示,当用户点击标记时,它会在标记上方显示一个标题,如下图所示:
总结
在本章中,您学习了如何向我们的应用添加地图。这需要我们在谷歌开发者控制台上创建一个项目,并配置我们的应用来访问必要的应用编程接口。一旦我们的应用完全配置完毕,我们就开始将地图添加到我们选择的视图中。我们讨论了用我们的MyMapFragment
处理片段中的片段(MapFragment
)。虽然单个的MapFragment
可以通过代码单独添加,但是将它放在另一个带有布局的片段中,如果需要的话,我们可以将其他 UI 小部件添加到页面中,比如FloatingActionButton
。最后,我们通过显示标记和位置信息使地图变得有用,这些信息是从 Parse 下载的。
在下一章中,您将学习如何调试和测试我们的应用。
版权属于:月萌API www.moonapi.com,转载请注明出处