·上一篇android项目案例1- 基于Android studio的仿微信底部导航栏实现·中分享了项目中的底部导航栏模块,有不懂的地方可以回到上一篇文章再看看,今天我要介绍一下我项目中的另一个百度地图模块。接下来进入主题!!!!
百度地图有以下功能:
1. 定位
2. 选择不同的地图类型后显示不同的地图
一.在百度地图开发者平台上申请API Key
百度地图开发者平台地址:http://lbsyun.baidu.com/index.php?title=androidsdk。点击界面的“获取密钥”,进入界面之后,点击“创建应用”按钮。将应用类型选择为“Android SDK”,填写你的项目应用名称即在Android studio中创建的项目名称、查看发布版本SHA1、开发版本SHA1,填写项目包名。完成后点击提交即可成为百度开发者,获得密钥即应用AK。
1.获取开发版SHA1:
输入命令:keytool -list -v -keystore debug.keystore,回车
输入密钥库口令:android(系统默认)回车。
方法1:
打开你的安卓ADB目录,一般在C盘的用户目录中以.android为文件名。
这个debug文件就是获取SHA1值的文件。接下来WIN+R,输入cmd。来到命令窗口界面:先输入cd .android来到这个文件夹中之后输入keytool -list -v -keystore debug.keystore
方法2:
在android studio的项目中查找开发版SHA1。
2.获取发布版SHA1:
要想获取发布版的SHA1的值,必须先对项目进行签名,如何对项目进行签名的,详情请看本人觉得不错,转载的博客:Android移动开发-如何在AndroidStudio里进行对应用程序进行签名,项目签名后可以直接用Android Studio提供的命令控制台Terminal输入命令时输入“cd 自己应用签名的jks文件保存的文件目录”然后接着回车,比如:cd D:\AndroidStudio\AndroidKey\BaiduMapTest1,接着在命令行里输入keytool -list -v -keystore jks文件名,比如:keytool -list -v -keystore BaiduMapTest.jks,接着按回车,然后输入秘钥,回车(秘钥库口令是看不到的)。如下图所示:
3.申请百度地图的API Key
得到发布版本SHA1、开发版本SHA1后,在百度地图开发者中心的创建应用里分别输入应用名称,应用类型,开发版和发布版的SHA1的值,包名 后点击提交,就能申请到了百度地图的API Key了。如下图所示
获取密钥成功(API key)
二.集成百度地图
1.上百度地图开发者网站下载百度地图SDK
2.将BaiduLBS_Android.jarr文件复制到libs目录中。
3.在main文件下新建JniLibs文件夹,将剩下的文件拷贝到里面。
4.在build.gradle文件中设置
工程配置还需要把jar包集成到自己的工程中,如图上图所示,放入libs目录下。将每个jar文件导入到工程中。对应在build.gradle生成工程所依赖的jar文件说明,如下所示:
ndk {
abiFilters "armeabi","armeabi-v7a","x86"
}
packagingOptions {
exclude "lib/libssl.so"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
main {
jniLibs.srcDir 'libs'
//说明so的路径为该libs路径,关联所有地图SDK的so文件
}
}
5.在项目中的AndroidManifest.xm文件中配置相关数据
<!-- 百度API所需权限 -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<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.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 百度地图API KEY -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="Ee5xOWrrxfNSkBqmLNAYdxr9ij2roADX" />
<!-- 百度定位服务 -->
<service
android:name="com.baidu.location.f"
android:enabled="true"
android:process=":remote" />
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="21" />
6.在布局xml文件中添加地图控件
<?xml version="1.0" encoding="utf-8"?>
<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">
<com.baidu.mapapi.map.MapView
android:id="@+id/id_bmapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center_vertical"
android:paddingLeft="3dp"
android:text="百度地图"
android:textColor="#FF4500"
android:textSize="20sp" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
7.创建Activity,实现地图功能。
package com.CWT.navigation.fragment.TabMapFragment;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.PopupMenu;
import android.widget.Toast;
import com.CWT.navigation.R;
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.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
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.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
public class TabMapFragment extends Fragment{
private static final int BAIDU_READ_PHONE_STATE = 100;
private MapView mMapView = null;
private BaiduMap mBaiduMap;
private LocationClient mlocationClient;
private MylocationListener mlistener;
private Context context;
private double mLatitude;
private double mLongitude;
private float mCurrentX;
private Button mGetMylocationBN;
PopupMenu popup = null;
private Activity mParentActivity = null;
//自定义图标
private BitmapDescriptor mIconLocation;
private MyOrientationListener myOrientationListener;
//定位图层显示方式
private MyLocationConfiguration.LocationMode locationMode;
// public TabMapFragment(Context c){
// this.context = c;
// }
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//引入我们的布局
return inflater.inflate(R.layout.fragment_tab_map, container, false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mParentActivity = this .getActivity();
Log.d("-----------------------", mParentActivity.getApplicationContext().toString());
SDKInitializer.initialize(mParentActivity.getApplicationContext()); //这里可以了
//剩下是baidu初始化找不到库的问题,去看例子
//mParentActivity.setContentView(R.layout.fragment_tab_map);
this.context =mParentActivity.getApplicationContext();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initView();
//判断是否为Android 6.0 以上的系统版本,如果是,需要动态添加权限
if (Build.VERSION.SDK_INT >= 23) {
showLocMap();
} else {
initLocation();//initLocation为定位方法
}
setHasOptionsMenu(true);
}
private void initView() {
mMapView = (MapView) mParentActivity.findViewById(R.id.id_bmapView);
mBaiduMap = mMapView.getMap();
//根据给定增量缩放地图级别
MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(18.0f);
mBaiduMap.setMapStatus(msu);
MapStatus mMapStatus;//地图当前状态
MapStatusUpdate mMapStatusUpdate;//地图将要变化成的状态
mMapStatus = new MapStatus.Builder().overlook(-45).build();
mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
mBaiduMap.setMapStatus(mMapStatusUpdate);
}
/**
* 定位方法
*/
private void initLocation() {
locationMode = MyLocationConfiguration.LocationMode.NORMAL;
//定位服务的客户端。宿主程序在客户端声明此类,并调用,目前只支持在主线程中启动
mlocationClient = new LocationClient(context);
mlistener = new MylocationListener();
//注册监听器
mlocationClient.registerLocationListener(mlistener);
//配置定位SDK各配置参数,比如定位模式、定位时间间隔、坐标系类型等
LocationClientOption mOption = new LocationClientOption();
//设置坐标类型
mOption.setCoorType("bd09ll");
//设置是否需要地址信息,默认为无地址
mOption.setIsNeedAddress(true);
//设置是否打开gps进行定位
mOption.setOpenGps(true);
//设置扫描间隔,单位是毫秒,当<1000(1s)时,定时定位无效
int span = 1000;
mOption.setScanSpan(span);
//设置 LocationClientOption
mlocationClient.setLocOption(mOption);
//初始化图标,BitmapDescriptorFactory是bitmap 描述信息工厂类.
mIconLocation = BitmapDescriptorFactory
.fromResource(R.drawable.icon_geo);
myOrientationListener = new MyOrientationListener(context);
//通过接口回调来实现实时方向的改变
myOrientationListener.setOnOrientationListener(new MyOrientationListener.OnOrientationListener() {
@Override
public void onOrientationChanged(float x) {
mCurrentX = x;
}
});
}
@Override
public void onStart() {
super.onStart();
//开启定位
mBaiduMap.setMyLocationEnabled(true);
if (!mlocationClient.isStarted()) {
mlocationClient.start();
}
myOrientationListener.start();
}
@Override
public void onStop() {
super.onStop();
//停止定位
mBaiduMap.setMyLocationEnabled(false);
mlocationClient.stop();
myOrientationListener.stop();
}
@Override
public void onResume() {
super.onResume();
mMapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mMapView.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
mMapView.onDestroy();
}
/**
* 获取我的定位
*/
public void getMyLocation() {
LatLng latLng = new LatLng(mLatitude, mLongitude);
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
mBaiduMap.setMapStatus(msu);
}
/**
* 菜单栏
* @param menu
* @param inflater
*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_main, menu);
}
/**
* 菜单项的选择
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.id_map_common:
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
break;
case R.id.id_map_site:
mBaiduMap.setMapType(BaiduMap.MAP_TYPE_SATELLITE);
break;
case R.id.id_map_traffic:
if (mBaiduMap.isTrafficEnabled()) {
mBaiduMap.setTrafficEnabled(false);
item.setTitle("实时交通(off)");
} else {
mBaiduMap.setTrafficEnabled(true);
item.setTitle("实时交通(on)");
}
break;
case R.id.id_map_mlocation:
getMyLocation();
break;
case R.id.id_map_model_common:
//热力图
mBaiduMap.setBaiduHeatMapEnabled(true);
break;
}
return true;
}
/**
* 所有的定位信息都通过接口回调来实现
*/
public class MylocationListener implements BDLocationListener {
//定位请求回调接口
private boolean isFirstIn = true;
//定位请求回调函数,这里面会得到定位信息
@Override
public void onReceiveLocation(BDLocation bdLocation) {
//BDLocation 回调的百度坐标类,内部封装了如经纬度、半径等属性信息
//MyLocationData 定位数据,定位数据建造器
/**
* 可以通过BDLocation配置如下参数
* 1.accuracy 定位精度
* 2.latitude 百度纬度坐标
* 3.longitude 百度经度坐标
* 4.satellitesNum GPS定位时卫星数目 getSatelliteNumber() gps定位结果时,获取gps锁定用的卫星数
* 5.speed GPS定位时速度 getSpeed()获取速度,仅gps定位结果时有速度信息,单位公里/小时,默认值0.0f
* 6.direction GPS定位时方向角度
* */
mLatitude = bdLocation.getLatitude();
mLongitude = bdLocation.getLongitude();
MyLocationData data = new MyLocationData.Builder()
.direction(mCurrentX)//设定图标方向
.accuracy(bdLocation.getRadius())//getRadius 获取定位精度,默认值0.0f
.latitude(mLatitude)//百度纬度坐标
.longitude(mLongitude)//百度经度坐标
.build();
//设置定位数据, 只有先允许定位图层后设置数据才会生效,参见 setMyLocationEnabled(boolean)
mBaiduMap.setMyLocationData(data);
//配置定位图层显示方式,三个参数的构造器
/**
* 1.定位图层显示模式
* 2.是否允许显示方向信息
* 3.用户自定义定位图标
* */
MyLocationConfiguration configuration
= new MyLocationConfiguration(locationMode, true, mIconLocation);
//设置定位图层配置信息,只有先允许定位图层后设置定位图层配置信息才会生效,参见 setMyLocationEnabled(boolean)
mBaiduMap.setMyLocationConfigeration(configuration);
//判断是否为第一次定位,是的话需要定位到用户当前位置
if (isFirstIn) {
//地理坐标基本数据结构
LatLng latLng = new LatLng(bdLocation.getLatitude(), bdLocation.getLongitude());
//描述地图状态将要发生的变化,通过当前经纬度来使地图显示到该位置
MapStatusUpdate msu = MapStatusUpdateFactory.newLatLng(latLng);
//改变地图状态
mBaiduMap.setMapStatus(msu);
isFirstIn = false;
Toast.makeText(context, "您当前的位置为:" + bdLocation.getAddrStr(),Toast.LENGTH_LONG).show();
}
}
}
/**
* Android 6.0 以上的版本的定位方法
*/
public void showLocMap() {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED
|| ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(getContext(), "没有权限,请手动开启定位权限", Toast.LENGTH_SHORT).show();
// 申请一个(或多个)权限,并提供用于回调返回的获取码(用户定义)
ActivityCompat.requestPermissions(mParentActivity,new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.READ_PHONE_STATE
}, BAIDU_READ_PHONE_STATE);
}
else {
initLocation();
}
}
//Android 6.0 以上的版本申请权限的回调方法
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
// requestCode即所声明的权限获取码,在checkSelfPermission时传入
case BAIDU_READ_PHONE_STATE:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 获取到权限,作相应处理(调用定位SDK应当确保相关权限均被授权,否则可能引起定位失败)
initLocation();
} else {
// 没有获取到权限,做特殊处理
Toast.makeText(getContext(), "获取位置权限失败,请手动开启", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
}
完成以上全部步骤,即可运行项目,
效果图如下:
请各位大神指教,本博文内容可能写的有错误,但程序没错误,程序是我调了很久,请教了老师后才完成的,期间跳了很多坑,也填了很多坑,希望本博文能够帮到大家。