实验完成时间:2020/12/23 18:00
windows 10系统详细配置如下:
笔记本详细配置如下:
AndroID Studio版本:
其他信息如工程gradle
信息都在工程文件中可以找到。
实验目的学会使用加速度传感器学会使用地磁传感器学会获取经纬度接入百度地图 API掌握少量的百度地图 API 接口实验内容初始界面仍为摇一摇跳转后的界面为百度地图地图定位在目前的经纬度通过对少量百度地图API的调用以及对传感器的使用,达到摇一摇定位的目的
增加内容:
摇一摇跳转至附近的娱乐场所记录摇一摇得到的娱乐场所列表点击摇一摇得到的娱乐场所可以调用百度地图API的步行导航功能实验步骤一、 获取百度地图API使用权限,申请百度地图AK
获取开发密钥(AK)
申请地址:http://lbsyun.baidu.com/apiconsole/key
百度教程地址:http://lbsyun.baidu.com/index.php?title=androidsdk/guide/create-project/ak
登录百度账号
登录后将进入API控制台,如下图:
点击“创建应用”开始申请开发密钥,如下图:
填写应用名称,注意应用类型选择“AndroID SDK”、正确填写SHA1 和 程序包名(SHA1和包名的获取方法见下文)。如图:
通过androID studio的AndroIDManifest.xml文件查看Packagename
通过命令行查看SHA1(默认没有密码,口令直接回车即可)
上面找到的其实是deBUG(开发板SHA1),发布版SHA1其实是另一种方法:
使用任意androID studio工程生成apk,步骤:Build->Build Bundle(s)/APK(s)->Build APK(s)
在工程目录/app/build/outputs/apk/deBUG中更改apk的后缀为zip文件并解压
进入解压后的meta-inf目录
在meta-inf目录下打开cmd,输入命令 :keytool -printcert -file CERT.RSA 这里将会显示出MD5和SHA1签名
使用上面的SHA1重新申请key,Packagename:AndroIDMainifest.xml中的包名。
输入得到的Packagename和SHA1,并点击提交
就得到了访问应用的AK
二、 使用百度地图API 显示地图、定位
应用申请权限
<!-- 以下权限开启地图服务 --><!-- 访问网络,进行地图相关业务数据请求,包括地图数据,路线规划,POI检索等 --><uses-permission androID:name="androID.permission.INTERNET" /> <!-- 获取网络状态,根据网络状态切换进行数据请求网络转换 --><uses-permission androID:name="androID.permission.ACCESS_NETWORK_STATE" /> <!-- 读取外置存储。如果开发者使用了so动态加载功能并且把so文件放在了外置存储区域,则需要申请该权限,否则不需要 --><uses-permission androID:name="androID.permission.READ_EXTERNAL_STORAGE" /> <!-- 写外置存储。如果开发者使用了离线地图,并且数据写在外置存储区域,则需要申请该权限 --><uses-permission androID:name="androID.permission.VIBRATE" /><uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE" /><!-- 以下权限用于开启定位服务 --><!-- 这个权限用于进行网络定位 --><uses-permission androID:name="androID.permission.ACCESS_COARSE_LOCATION" /><!-- 这个权限用于访问GPS定位 --><uses-permission androID:name="androID.permission.ACCESS_FINE_LOCATION" /><!-- 以下权限用于开启定位服务 --> <service androID:name="com.baIDu.location.f" androID:enabled="true" androID:process=":remote"/>
初始化SDK组件
//在使用SDK各组件之前初始化context信息,传入ApplicationContextSDKInitializer.initialize(this);//自4.3.0起,百度地图SDK所有接口均支持百度坐标和国测局坐标,用此方法设置您使用的坐标类型.//包括BD09LL和GCJ02两种坐标,默认是BD09LL坐标。SDKInitializer.setCoordType(CoordType.BD09LL);
注意最好在任何其他组件都没有使用百度地图API之前就初始化
使用百度地图API
初始化
// ----------------------------------- 初始化百度地图 --------------------------------- // mMapVIEw = findVIEwByID(R.ID.bmapVIEw); mTextVIEw = findVIEwByID(R.ID.tv); mPoiSearch = PoiSearch.newInstance(); mPoiSearch.setonGetPoiSearchResultListener(this); // 更改地图类型 mBaIDuMap = mMapVIEw.getMap(); mBaIDuMap.setMapType(BaIDuMap.MAP_TYPE_SATELliTE); // 设置定位服务开始 mBaIDuMap.setMyLocationEnabled(true); //定位初始化 mLocationClIEnt = new LocationClIEnt(getApplicationContext()); //通过LocationClIEntoption设置LocationClIEnt相关参数 LocationClIEntoption option = new LocationClIEntoption(); option.setLocationMode(LocationClIEntoption.LocationMode.Device_Sensors); // 定位模式是仅限设备模式,也就是仅允许GPS来定位。 option.setopenGps(true); // 打开gps option.setCoorType("bd09ll"); // 设置坐标类型 option.setScanSpan(1000); //设置打开自动回调位置模式,该开关打开后,期间只要定位SDK检测到位置变化就会主动回调给开发者 option.setIsNeedAddress(true); //可选,是否需要地址信息,默认为不需要,即参数为false //如果开发者需要获得当前点的地址信息,此处必须为true option.setNeednewVersionRgc(true); //可选,设置是否需要最新版本的地址信息。默认需要,即参数为true
// 自定义定位指针
// MyLocationConfiguration.LocationMode mCurrentMode = MyLocationConfiguration.LocationMode.COMPASS;
// BitmapDescriptor mCurrentMarker = BitmapDescriptorFactory.fromresource(R.drawable.ic_launcher_background);
// MyLocationConfiguration myLocationConfiguration = new MyLocationConfiguration(mCurrentMode, true,
// mCurrentMarker, 0xAAFFFF88, 0xAA00FF00);
// mBaIDuMap.setMyLocationConfiguration(myLocationConfiguration);//设置locationClIEntoption mLocationClIEnt.setLocoption(option); //注册LocationListener监听器 MyLocationListener myLocationListener = new MyLocationListener(); mLocationClIEnt.registerLocationListener(myLocationListener); //开启地图定位图层 mLocationClIEnt.start(); // 搜索时不重复,使用HashSet来支持 mHashLocStr = new HashSet<>(); // 一开始搜索的半径和接收的结果数 mRadius = 1000; mPageCapacity = 10;
声明地址更改Listener并在Listener中更新位置信息
public class MainActivity extends AppCompatActivity implements OnGetPoiSearchResultListener, SensorEventListener{ ... /** * LocationListener 不断接收定位的回调并改变当前的位置信息 */ public class MyLocationListener extends BDAbstractLocationListener { private boolean isFirstLocate = true; @OverrIDe public voID onReceiveLocation(BDLocation location) { //mapVIEw 销毁后不在处理新接收的位置 if (location == null || mMapVIEw == null){ return; } mBDLocation = location; addressAdapter.setStartLocation(mBDLocation); // 如果是第一次定位 LatLng ll = new LatLng(location.getLatitude(), location.getLongitude()); if (isFirstLocate) { isFirstLocate = false; //给地图设置状态 mBaIDuMap.animateMapStatus(MapStatusUpdateFactory.newLatLng(ll)); } // 编辑Locdata并改变当前地图的信息 MyLocationData locdata = new MyLocationData.Builder() .accuracy(location.geTradius()) // 此处设置开发者获取到的方向信息,顺时针0-360 .direction(location.getDirection()).latitude(location.getLatitude()) .longitude(location.getLongitude()).build(); mBaIDuMap.setMyLocationData(locdata); Log.d("0", "onReceiveLocation: 定位到 " + location.getAddrstr()); mCity = location.getCity(); // 显示当前信息 StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("\n当前地址:" + location.getAddrstr()); stringBuilder.append("\n经度:" + location.getLatitude()); stringBuilder.append("\n纬度:"+ location.getLongitude());// stringBuilder.append("\n状态码:"+ location.getLocType());// stringBuilder.append("\n国家:" + location.getCountry());// stringBuilder.append("\n城市:"+ location.getCity());// stringBuilder.append("\n区:" + location.getdistrict());// stringBuilder.append("\n街道:" + location.getStreet()); mTextVIEw.setText(stringBuilder.toString()); } }}
将
MainActivity
声明为OnGetPoiSearchResultListener
来支持Poi检索功能,声明MyLocationListener
来支持定位功能生命周期管理
@OverrIDe protected voID onResume() { mMapVIEw.onResume(); super.onResume(); } @OverrIDe protected voID onPause() { mMapVIEw.onPause(); // 务必要在pause中注销 mSensorManager // 否则会造成界面退出后摇一摇依旧生效的BUG if (mSensorManager != null) { mSensorManager.unregisterListener(this); } super.onPause(); } @OverrIDe protected voID onDestroy() { mLocationClIEnt.stop(); mBaIDuMap.setMyLocationEnabled(false); mMapVIEw.onDestroy(); mMapVIEw = null; super.onDestroy(); }
在进行百度地图API的使用,需要特别注意生命周期的管理,否则可能造成定位不准,后台耗电量巨大的隐患。
三、 整合摇一摇来调用百度地图API
实验结果初始化摇一摇组件
// ---------------------------------初始化摇一摇--------------------------------------- // mHandler = new MyHandler(this); //初始化SoundPool mSoundPool = new SoundPool(1, AudioManager.STREAM_SYstem, 5); mWeiChatAudio = mSoundPool.load(this, R.raw.weichat_audio, 1); //获取Vibrator震动服务 mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE); // 摇一摇的两个分离界面 mtopLayout = findVIEwByID(R.ID.top_layout); mBottomLayout = findVIEwByID(R.ID.bottom_layout); //获取 SensorManager 负责管理传感器 mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE)); if (mSensorManager != null) { //获取加速度传感器 mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (mAccelerometerSensor != null) { mSensorManager.registerListener(this, mAccelerometerSensor, SensorManager.SENSOR_DELAY_UI); } }
摇一摇调用
sensorManager
来监听手机的位置变化,如果三维的位置变化达到一定程度,我们就认为手机被摇晃了,此时监听位置变化的函数是onSensorChanged
函数,在这个函数中进行调整即可。调用传感器来调用百度地图API和动画
@OverrIDepublic voID onSensorChanged(SensorEvent event) { int type = event.sensor.getType(); if (type == Sensor.TYPE_ACCELEROMETER) { //获取三个方向值 float[] values = event.values; float x = values[0]; float y = values[1]; float z = values[2]; if ((Math.abs(x) > 17 || Math.abs(y) > 17 || Math .abs(z) > 17) && !isShake) { isShake = true; Thread thread = new Thread() { @OverrIDe public voID run() { super.run(); try { Log.d(TAG, "onSensorChanged: 摇动"); searchPoiNearBy(); //开始震动 发出提示音 展示动画效果 mHandler.obtainMessage(START_SHAKE).sendToTarget(); Thread.sleep(500); //再来一次震动提示 mHandler.obtainMessage(AGAIN_SHAKE).sendToTarget(); Thread.sleep(500); mHandler.obtainMessage(END_SHAKE).sendToTarget();
} catch (InterruptedException e) { e.printstacktrace(); } } }; thread.start(); }}
}
@OverrIDe
public voID onAccuracyChanged(Sensor sensor, int accuracy) {
}/**
handler 接收摇一摇产生的信息并作出对应的 *** 作
START_SHAKE 开始摇晃
AGAIN_SHAKE 没结束摇晃之前再次摇晃
END_SHAKE 结束摇晃
*/
private static class MyHandler extends Handler {
private WeakReferencemReference;
private MainActivity mActivity;public MyHandler(MainActivity activity) {
mReference = new WeakReference(activity);
if (mReference != null) {
mActivity = mReference.get();
}
}@OverrIDe
public voID handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case START_SHAKE:
//This method requires the caller to hold the permission VIBRATE.
mActivity.mVibrator.vibrate(300);
//发出提示音
mActivity.mSoundPool.play(mActivity.mWeiChatAudio, 1, 1, 0, 0, 1);mActivity.startAnimation(false);//参数含义: (不是回来) 也就是说两张图片分散开的动画 break; case AGAIN_SHAKE: mActivity.mVibrator.vibrate(300); break; case END_SHAKE: //整体效果结束, 将震动设置为false mActivity.isShake = false; // 展示上下两种图片回来的效果 mActivity.startAnimation(true); break; }
}
}
如上代码,我们在`onSensorChanged`中调用了调用百度地图API的函数`searchPoiNearBy`来寻找附近的娱乐场所:```java // 搜索附近的娱乐设施 private voID searchPoiNearBy() { String cityStr = mCity; // 获取检索关键字 String keyWordStr = "娱乐"; if (TextUtils.isEmpty(cityStr) || TextUtils.isEmpty(keyWordStr)) { return; } LatLng ll = new LatLng(mBDLocation.getLatitude(), mBDLocation.getLongitude()); // 搜索附近的娱乐场所 mPoiSearch.searchNearby((new PoiNearbySearchOption()) .location(ll) .keyword(keyWordStr) .pageCapacity(mPageCapacity) .pageNum(0) .radius(mRadius)); }
该函数通过API
searchNearby
来查找附近的娱乐设施,最后通过本身的查找结果函数onGetPoiResult
来定位到该位置并加入到recycler vIEw
中去:@OverrIDe // 在poiSearch完成之后对得到的结果进行处理并展示到recycler VIEw中 public voID onGetPoiResult(PoiResult poiResult) { List<PoiInfo> poiInfos = poiResult.getAllPoi(); if (poiInfos.size() <= 0 || poiResult.error == SearchResult.ERRORNO.RESulT_NOT_FOUND) { Toast.makeText(MainActivity.this, "未找到结果", Toast.LENGTH_LONG).show(); // 没找到,说明附近娱乐场所很少 mRadius *= 2; mPageCapacity *= 2; return; } // 将地图平移到 latLng 位置 int index = (int)(Math.random() * poiInfos.size()) % poiInfos.size(); PoiInfo poiInfo = poiInfos.get(index); int isSelected = 0; for (int i = 0; i < poiInfos.size(); i ++) { index = (int)(Math.random() * poiInfos.size()) % poiInfos.size(); poiInfo = poiInfos.get(index); if (!mHashLocStr.contains(poiInfo.getname())) { isSelected = 1; break; } } if (isSelected == 0) { // 找到了但是差不多都输出过,说明已经摇了很多次 mRadius *= 2; mPageCapacity *= 2; Toast.makeText(this, "你是真的挑三拣四,建议卸载本APP", Toast.LENGTH_SHORT).show(); return; } // 加入HashSet以避免重复 mHashLocStr.add(poiInfo.getname()); // 加入AddressAdapter以显示摇出的地址 addressAdapter.addItem(poiInfo); // 定位到摇到的地址的位置 LatLng latLng = poiInfos.get(index).getLocation(); MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latLng); mBaIDuMap.setMapStatus(mapStatusUpdate); // 添加指示标志 MarkerOptions markerOptions = new MarkerOptions() .position(poiInfo.getLocation()) .icon(mBitmapDescWaterDrop); InfoWindow infoWindow = getPoiInfoWindow(poiInfo); markerOptions.infoWindow(infoWindow); Marker marker = (Marker) mBaIDuMap.addOverlay(markerOptions); } // 在摇到的地址上方显示当前地址的名字 private InfoWindow getPoiInfoWindow(PoiInfo poiInfo) { TextVIEw textVIEw = new TextVIEw(this); textVIEw.setText(poiInfo.getname()); textVIEw.setpadding(10, 5, 10, 5); textVIEw.setBackground(this.getResources().getDrawable(R.drawable.bg_info)); InfoWindow infoWindow = new InfoWindow(textVIEw, poiInfo.getLocation(), -150); return infoWindow; }
至于
RecyclerVIEw
就是简单的线性vIEw对ArrayList
进行的封装。生命周期管理
传感器是一个非常耗电的设备,并且极易影响到其他APP的使用,所以它的生命周期管理也十分重要:
@OverrIDeprotected voID onStart() { super.onStart(); //获取 SensorManager 负责管理传感器 mSensorManager = ((SensorManager) getSystemService(SENSOR_SERVICE)); if (mSensorManager != null) { //获取加速度传感器 mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (mAccelerometerSensor != null) { mSensorManager.registerListener(this, mAccelerometerSensor, SensorManager.SENSOR_DELAY_UI); } }}@OverrIDeprotected voID onResume() { mMapVIEw.onResume(); super.onResume();}@OverrIDeprotected voID onPause() { mMapVIEw.onPause(); // 务必要在pause中注销 mSensorManager // 否则会造成界面退出后摇一摇依旧生效的BUG if (mSensorManager != null) { mSensorManager.unregisterListener(this); } super.onPause();}@OverrIDeprotected voID onDestroy() { mLocationClIEnt.stop(); mBaIDuMap.setMyLocationEnabled(false); mMapVIEw.onDestroy(); mMapVIEw = null; super.onDestroy();}
首先,和百度地图API一样的是在APP开始时初始化,在APP关闭时摧毁,不同的是,在应用未被关闭而是切换(Pause)期间,传感器必须被注销,否则在其他APP使用时仍然有摇一摇的功能,在重新回到该APP(Start)时,必须检查传感器的状态以保证摇一摇的功能可用。
APP图标@H_121_419@ | APP初始界面@H_121_419@ |
---|---|
摇晃一次 | 调用百度地图进行导航 |
摇晃三次 | |
得到的APP不能使用AndroID Studio上的虚拟手机端来跑,因为虚拟的手机是没有GPS的,不能够正常使用定位的功能
得到的源码不一定能够在其他电脑上跑的通,因为百度地图API限制了SHA1和包名,所以如果想要正常的使用本APP,可以使用项目工程目录中./app/build/outputs/apk/deBUG/app-deBUG.apk
这个文件来安装并运行
或者通过更改AndroIDManifest.xml
中的百度地图APIkey
,用自己的百度地图APIkey
来调试本源码
以上是内存溢出为你收集整理的中级实训Android学习记录——实训报告全部内容,希望文章能够帮你解决中级实训Android学习记录——实训报告所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)