1、百度地图的问题
地图的相关操作步骤根据百度地图的操作文档进行,就可以在项目中进行百度地图的访问(地图SDK地址:http://lbsyun.baidu.com/index.php?title=androidsdk),
总结一下地图的几个操作步骤:
1.注册和获取秘钥(百度地图 SDK开发密钥的申请地址为:http://lbsyun.baidu.com/apiconsole/key)
2.获取安全码
3.copy相关开发包
4.实现地图功能,以及相关配置信息
定位功能参考相关文档可以进行功能实现
地图权限分为两块,一块是网络访问权限,一块是GPS定位
1.1、定位问题:
定位需要在项目中添加添加定位权限,定位参考demo地址:http://lbsyun.baidu.com/index.php?title=android-locsdk
<!-- 这个权限用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!-- 这个权限用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
由于目前的android版本升级,6.0以上需要动态申请权限,所以在某些手机上面必须要动态申请权限
XXPermissions.with(getActivity())
//请求获取拍照权限
.permission(Permission.CAMERA)
.request(new OnPermission() {
@Override
public void hasPermission(List<String> granted, boolean isAll) {
if (isAll) {
//扫码
Intent intent = new Intent(getActivity(), CaptureActivity.class);
intent.putExtra("fragmentName", "AbnormalFragment");
startActivityForResult(intent, Contacts.REQUESTCODE_ABNORMAL_FRAGMENT_CAPTURE);
} else {
Toast.makeText(getActivity(), "获取权限成功,部分权限未正常授予", Toast.LENGTH_SHORT).show();
}
}
@Override
public void noPermission(List<String> denied, boolean quick) {
if (quick) {
Toast.makeText(getActivity(), "被永久拒绝授权,请手动授予权限", Toast.LENGTH_SHORT).show();
//如果是被永久拒绝就跳转到应用权限系统设置页面
XXPermissions.gotoPermissionSettings(getActivity());
} else {
Toast.makeText(getActivity(), "获取权限失败", Toast.LENGTH_SHORT).show();
}
}
});
需要动态请求的权限目录如下:
public static final String REQUEST_INSTALL_PACKAGES = "android.permission.REQUEST_INSTALL_PACKAGES"; // 8.0及以上应用安装权限
public static final String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW"; // 6.0及以上悬浮窗权限
public static final String READ_CALENDAR = "android.permission.READ_CALENDAR"; // 读取日程提醒
public static final String WRITE_CALENDAR = "android.permission.WRITE_CALENDAR"; // 写入日程提醒
public static final String CAMERA = "android.permission.CAMERA"; // 拍照权限
public static final String READ_CONTACTS = "android.permission.READ_CONTACTS"; // 读取联系人
public static final String WRITE_CONTACTS = "android.permission.WRITE_CONTACTS"; // 写入联系人
public static final String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; // 访问账户列表
public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION"; // 获取精确位置
public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION"; // 获取粗略位置
public static final String RECORD_AUDIO = "android.permission.RECORD_AUDIO"; // 录音权限
public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"; // 读取电话状态
public static final String CALL_PHONE = "android.permission.CALL_PHONE"; // 拨打电话
public static final String READ_CALL_LOG = "android.permission.READ_CALL_LOG"; // 读取通话记录
public static final String WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG"; // 写入通话记录
public static final String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL"; // 添加语音邮件
public static final String USE_SIP = "android.permission.USE_SIP"; // 使用SIP视频
public static final String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS"; // 处理拨出电话
public static final String ANSWER_PHONE_CALLS = "android.permission.ANSWER_PHONE_CALLS";// 8.0危险权限:允许您的应用通过编程方式接听呼入电话。要在您的应用中处理呼入电话,您可以使用 acceptRingingCall() 函数
public static final String READ_PHONE_NUMBERS = "android.permission.READ_PHONE_NUMBERS";// 8.0危险权限:权限允许您的应用读取设备中存储的电话号码
public static final String BODY_SENSORS = "android.permission.BODY_SENSORS"; // 传感器
public static final String SEND_SMS = "android.permission.SEND_SMS"; // 发送短信
public static final String RECEIVE_SMS = "android.permission.RECEIVE_SMS"; // 接收短信
public static final String READ_SMS = "android.permission.READ_SMS"; // 读取短信
public static final String RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH"; // 接收WAP PUSH信息
public static final String RECEIVE_MMS = "android.permission.RECEIVE_MMS"; // 接收彩信
public static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE"; // 读取外部存储
public static final String WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE"; // 写入外部存储
1.2、地图的网络权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
//获取设备网络状态,禁用后无法获取网络状态
<uses-permission android:name="android.permission.INTERNET"/>
//网络权限,当禁用后,无法进行检索等相关业务
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
//读取设备硬件信息,统计数据
<uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
//读取系统信息,包含系统版本等信息,用作统计
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
//获取设备的网络状态,鉴权所需网络代理
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
//允许sd卡写权限,需写入地图数据,禁用后无法显示地图
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
//获取统计数据
<uses-permission android:name="android.permission.CAMERA" />
//使用步行AR导航,配置Camera权限
1.3 地图的BUG
1.3.1在实现的过程中 遇到一种状况,在进入界面中正常显示了当前定位之后,在手机上把网络或者GPS定位关闭了,之后,点击定位,程序崩溃的问题
处理方式:在MyLocationListener 中实现onLocDiagnosticMessage方法,该方法用于处理异常定位情况
衍生问题由于onLocDiagnosticMessage是优先于定位处理异常情况,所以在定位onReceiveLocation方法中需要处理返回的异常信息不再显示的问题
public class MyLocationListener extends BDAbstractLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
//得到当前的地址
adfState.setMapAddress(location.getAddrStr());
Log.e("是否是国外:", "" + (location.getLocationWhere() != BDLocation.LOCATION_WHERE_IN_CN));
//BDLocation.getLocationWhere()方法可获得当前定位点是否是国内,它的取值及含义如下:
//BDLocation.LOCATION_WHERE_IN_CN:当前定位点在国内;
//BDLocation.LOCATION_WHERE_OUT_CN:当前定位点在海外;
if (location.getLocationWhere() != BDLocation.LOCATION_WHERE_IN_CN) {
//定位失败会优先调用onLocDiagnosticMessage方法,该方法已经提示了错误信息了,所以就不用再提示
if (adfState.isShowMapError()) {
Toast.makeText(mActivity, "定位失败,请打开定位服务", Toast.LENGTH_SHORT).show();
}
mLocationClient.stop();
bdLocation = null;
} else {
bdLocation = location;
setMapAddress();
}
}
@Override
public void onLocDiagnosticMessage(int result, int type, String s) {
super.onLocDiagnosticMessage(result, type, s);
MapErrorUtil.showMapError(getActivity(), result, type);
//由于该方法是先于定位执行,所以在弹出提示之后就禁止在弹出错误信息
adfState.setShowMapError(false);
}
}
1.4 关于地图上,显示的定位图标偏移,不是垂直显示的问题
解决办法:在设置MyLocationData参数的时候,有个设置偏移度的方法direction(XX),XX代表偏移的度数,范围是(0-360),设置的度数不同,图标就会偏移相同的度数
要垂直显示,直接设置XX为0 就可以解决了
1.5 地图 经纬度转地址,地址转经纬度
解决方法: 在初始化地图时候实现GeoCoder这个类的setOnGetGeoCodeResultListener方法,就可以了
GeoCoder geoCoder;//定义一个变量
geoCoder = GeoCoder.newInstance();
//设置地址或经纬度反编译后的监听,这里有两个回调方法,
geoCoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
//经纬度转换成地址
@Override
public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
Toast.makeText(MapActivity.this, "找不到该地址!", Toast.LENGTH_SHORT).show();
}
LogUtils.e("地址:" + result.getAddress());
mapAddress = result.getAddress();
}
//把地址转换成经纬度
@Override
public void onGetGeoCodeResult(GeoCodeResult result) {
}
});
在地图定位的BaiduMap.OnMapClickListener 的onMapClick中注册该方法
BaiduMap.OnMapClickListener listene1 = new BaiduMap.OnMapClickListener() {
/**
* 地图单击事件回调函数
* @param point 点击的地理坐标
*/
@Override
public void onMapClick(LatLng point) {
//.... 其他的代码
// 设置反地理经纬度坐标,请求位置时,需要一个经纬度
geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(point));
}
@Override
public boolean onMapPoiClick(MapPoi mapPoi) {
return false;
}
};
2、APP重复点击,出现多次同样的响应
解决办法:在BaseActvity中实现onTouchEvent,dispatchTouchEvent方法,处理点击的时间间隔
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
// 判断连续点击事件时间差
if (DoubleClickUtil.isFastClick()) {
return true;
}
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// 判断连续点击事件时间差
if (DoubleClickUtil.isFastClick()) {
return true;
}
}
return super.onTouchEvent(event);
}
DoubleClickUtil.isFastClick()的代码实现:
/**
* 两次点击间隔不能少于500ms
*/
private static final int MIN_DELAY_TIME = 500;
private static long lastClickTime;
public static boolean isFastClick() {
boolean flag = true;
long currentClickTime = System.currentTimeMillis();
if ((currentClickTime - lastClickTime) >= MIN_DELAY_TIME) {
flag = false;
}
lastClickTime = currentClickTime;
return flag;
}
3、状态管理 界面数据信息
新增一个BaseState的状态管理器,复杂的界面新加一个状态管理,用于管理当前界面的数据处理
/**
* 全局基类管理状态
*
* @author Admin
*/
public abstract class BaseState {
/**
* 进入状态
*/
protected abstract void enterState();
/**
* 退出状态
*/
protected abstract void outState();
}