前言
我是一个在普通大学上学的孩子,主攻AR方向。我最近要通过unity3d来完成我的科研立项---AR指南针,当我开始这个项目时,我在想怎么做,首先在unity3d中调用AR摄像头不难,难就难在怎么获取到当前的经纬度,最好是能实现百度地图的功能,不要多的可以获取经纬度就行,所以我想到的百度地图的官方API,但是一个又一个的困难阻挡着我,因为百度地图api只提供Android,IOS和JavaScript的接口并没有跟Unity3d有任何联系,但是不能放弃啊,我又想到unity 3d可以跟Android开发融合在一起,于是我又从头开始学习Android开发,在学Android开发的这段日子里头发越来越少,我只要能够调用百度地图的定位功能就行!于是写下了这篇博客,希望能帮助大家!
一、准备工作
1、在eclipse中配置Android的环境,这个就先不说了,之后可能会写博客教大家怎么配置。
2、当我们配置好环境,用手机连一下真机,来试试自己的第一个app—helloAndroid。(记住这个开心的时候,后面掉头发的时候想一想)
3、去百度地图开放平台来注册账号,申请密钥,创建应用,如下图:
4、反正就是按照百度地图API上来,其他的就自己百度,不是我懒,这是一个学习的过程,所以不要怕麻烦
二、编写代码
(补充)我是照着慕课网上调用百度地图的课程来的,我现在把核心的代码贴出来,你如果也是的话,你会发现照着他打,一定成功不了,所以去下载我的源码,绝逼管用!
代码工程的目录:请注意我的版本号一定要一样!
libs目录:
注意(一定要将jar文件,导入(即build path 一下))接下来开始编写代码!
首先先将地图显示出来,MainActivity.java文件的代码,注意复制时包名(用自己的包名)
package com.test.app02;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.MapView;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
private MapView mMapView ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//在使用SDK各组件之前初始化context信息,传入ApplicationContext
//注意该方法要再setContentView方法之前实现
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mMapView = (MapView) findViewById(R.id.id_bmapView);
}
@Override
protected void onResume() {
super.onResume();
//在activity执行onResume时执行mMapView. onResume (),实现地图生命周期管理
mMapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//在activity执行onPause时执行mMapView. onPause (),实现地图生命周期管理
mMapView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
//在activity执行onDestroy时执行mMapView.onDestroy(),实现地图生命周期管理
mMapView.onDestroy();
}
}
然后就是activity.xml布局文件 ,这个文件就像是一个容器一样,你的各种标签比如button,text,title必须在这个文件定义,根据你的命名,才能在MainActivity.java文件中去调用。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<com.baidu.mapapi.map.MapView
android:id="@+id/id_bmapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
</RelativeLayout>
注意这个是我的文件,你粘贴过去后要看看,你的id是不是和我一样叫id_bmapView,不然会报错。
接下来就是AndroidManifest.xml,注意<meta-data>里面的密钥值,用你自己申请的,上面<uses-permisson>这是给你的应用添加的权
限,注意要写在application标签外面。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.app02"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="fudZW3z1ZYibdb9dP83L6DE3QPacUBY3" />
<activity
android:name=".MainActivity"
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>
</manifest>
三、成功运行
最后连上手机,打开开发者模式,然后在 eclipse中运行,会自动安装,一定要将手机联网,gps打开,如果报错,说明可能操作有问题,多试试几次。
到这里最最简单的调用百度地图就到处结束!
接下来就是,真正硬货了,实现百度地图的定位功能。
四、百度地图定位功能的实现
如果你是下载的最新版本的百度地图提供的jar包,那么你会绝望,因为,它会一直显示你在非洲的几内亚湾,出现这个的原因就是因为你的经纬度为空,程序没有从你的手机所在的地方获取到经度和纬度的值。所以不要在最新的版本里面调试了,下载我提供的版本,妥妥滴!接下来看代码!
1、libs目录
2、AndroidManifest.xml文件
这个相比较上个,除了添加了更多的权限以外,还有就是service标签,这个一定要添加上去,不然就定位不了
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.test.app03" android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="14"
android:targetSdkVersion="27" />
<!-- 百度地图API权限 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >
</uses-permission>
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >
</uses-permission>
<!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
</uses-permission>
<!-- 获取运营商信息,用于支持提供运营商信息相关的接口 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
</uses-permission>
<!-- 这个权限用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
</uses-permission>
<!-- 用于读取手机当前的状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" >
</uses-permission>
<!-- 写入扩展存储,向扩展卡写入数据,用于写入离线定位数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
</uses-permission>
<!-- 访问网络,网络定位需要上网 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- SD卡读取权限,用户写入离线定位数据 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >
</uses-permission>
<!-- 允许应用读取低级别的系统日志文件 -->
<uses-permission android:name="android.permission.READ_LOGS" >
</uses-permission>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<meta-data android:name="com.baidu.lbsapi.API_KEY"
android:value="7EILuUqjsawBtYay8VoKHGzdt7x3V8QO" />
<activity
android:name="com.test.app03.MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote">
</service>
</application>
</manifest>
3、main.xml 文件
接下来就是main.xml 文件,这个文件主要是添加几个选项,和value.xml一样的功能。
为什么我的这里多了一个menu的文件夹,是因为我建立工程时,没有选择empty project,而是默认一直next。如果看不懂就百度吧。
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.test.app03.MainActivity" >
<item
android:id="@+id/id_map_common"
android:showAsAction="never"
android:title="普通地图"/>
<item
android:id="@+id/id_map_site"
android:showAsAction="never"
android:title="卫星地图"/>
<item
android:id="@+id/id_map_traffic"
android:showAsAction="never"
android:title="实时交通(off)"/>
<item
android:id="@+id/id_map_location"
android:showAsAction="never"
android:title="我的位置"/>
</menu>
4、MainActivity.java
最后就是MainActivity.java,注释已经标识清楚,不懂地可以百度。请务必使用我的项目工程!
package com.test.app03;
import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.SDKInitializer;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity{
/**
* 定位SDK核心类
*/
private LocationClient locationClient;
/**
* 定位监听
*/
public MyLocationListenner myListener = new MyLocationListenner();
/**
* 百度地图控件
*/
private MapView mapView;
//private Context context;
private double mLatitude;
private double mLongtitude;
/**
* 百度地图对象
*/
private BaiduMap baiduMap;
boolean isFirstLoc = true; // 是否首次定位
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
/**
* 地图初始化
*/
//获取百度地图控件
mapView = (MapView) findViewById(R.id.id_bmapView);
//获取百度地图对象
baiduMap = mapView.getMap();
// 开启定位图层
baiduMap.setMyLocationEnabled(true);
/**
* 定位初始化
*/
//声明定位SDK核心类
locationClient = new LocationClient(this);
//注册监听
locationClient.registerLocationListener(myListener);
//定位配置信息
LocationClientOption option = new LocationClientOption();
option.setOpenGps(true); // 打开gps
option.setCoorType("bd09ll"); // 设置坐标类型
option.setScanSpan(1000);//定位请求时间间隔
locationClient.setLocOption(option);
//开启定位
locationClient.start();
}
/**
* 定位SDK监听函数
*/
public class MyLocationListenner implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
// map view 销毁后不在处理新接收的位置
if (location == null || mapView == null) {
return;
}
MyLocationData locData = new MyLocationData.Builder()
.accuracy(location.getRadius())
// 此处设置开发者获取到的方向信息,顺时针0-360
.direction(100).latitude(location.getLatitude())
.longitude(location.getLongitude()).build();
//给百度地图对象传入经纬度
baiduMap.setMyLocationData(locData);
if (isFirstLoc) {
isFirstLoc = false;
//定义一个经纬度的变量,将获取到的经纬度的值赋给这个变量
LatLng ll = new LatLng(location.getLatitude(),location.getLongitude());
//获取经度
mLatitude = location.getLatitude();
//获取纬度值
mLongtitude = location.getLongitude();
MapStatus.Builder builder = new MapStatus.Builder();
//控制缩放的尺寸
builder.target(ll).zoom(18.0f);
baiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(builder.build()));
}
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/*
* 下拉框控制地图的样式
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.id_map_common:
baiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
break;
case R.id.id_map_site:
baiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
break;
case R.id.id_map_traffic:
if (baiduMap.isTrafficEnabled()) {
baiduMap.setTrafficEnabled(false);
item.setTitle("实时交通(off)");
}else {
baiduMap.setTrafficEnabled(true);
item.setTitle("实时交通(on)");
}
break;
case R.id.id_map_location:
//调用获取我的位置的方法
centerToMyLocation();
break;
default:
break;
}
return super.onOptionsItemSelected(item);
}
//将mLatitude值和mLongtitude值传入
private void centerToMyLocation() {
LatLng latlng = new LatLng(mLatitude,mLongtitude);
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latlng);
baiduMap.animateMapStatus(msu);
}
@Override
protected void onPause() {
mapView.onPause();
super.onPause();
}
@Override
protected void onResume() {
mapView.onResume();
super.onResume();
}
@Override
protected void onDestroy() {
// 退出时销毁定位
locationClient.stop();
// 关闭定位图层
baiduMap.setMyLocationEnabled(false);
mapView.onDestroy();
mapView = null;
super.onDestroy();
}
}
最后,那个layout文件,和之前一样,直接粘贴就行了。
分享一下App的运行成果
相信大家,如果是按照我说的,而且能把代码看懂,就OK了,如果出现问题,看是不是跟我的代码有不一样的地方,不要害怕出现问题,敢于去解决,最最重要的是千万不要挠头发,不然头会很冷,哈哈^_^
下载地址:
https://download.csdn.net/download/lwd23333/10756334