封面画师:画师JW 封面ID:78143565
传感器的应用
本节案例需要在真机上进行测试 ,对于真机测试方法请看到 笔记—— Android图像处理与多媒体
本节案例需要在真机上进行测试 ,对于真机测试方法请看到 笔记—— Android图像处理与多媒体
什么是传感器
传感器 一种微型的物理设备 ,能够探测、感受到外界信号,并按一定规律转换成我们需要的信息。
传感器的坐标系统:
常用的传感器: 光线传感器、磁场传感器、加速度传感器、方向传感器等。
开发传感器应用的步骤:
获取SensorManager对象:使用getSystemService(Context.SENSOR_SERVICE)
获取指定类型的传感器:使用SensorManager的getDefaultSensor(int type)
方法
为指定传感器注册监听器:在Activity的onResume()
方法中调用SensorManager的registerListener()
方法。
在注册监听器时,需要我们实现SensorEventListener接口,然后我们需要重写:
onSensorChanged(SensorEvent event)
:传感器的值 发生变化的时候调用
onAccuracyChanged(Sensor sensor, int accuracy)
:传感器的精度 发生变化时调动
使用光线传感器获取光的强度
编写布局资源文件activity_main.xml,完成界面布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <LinearLayout ... android:orientation ="vertical" android:gravity ="top|center_horizontal" > <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="光线传感器" android:textSize ="40sp" /> <EditText android:id ="@+id/editText" android:layout_width ="310dp" android:layout_height ="wrap_content" android:textSize ="30sp" /> </LinearLayout >
编写MainActivity.java实现使用光线传感器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public class MainActivity extends AppCompatActivity implements SensorEventListener { private EditText textLIGHT; private SensorManager sensorManager; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); textLIGHT = findViewById(R.id.editText); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); } @Override protected void onResume () { super .onResume(); sensorManager.registerListener(this ,sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT), SensorManager.SENSOR_DELAY_GAME); } @Override protected void onPause () { super .onPause(); sensorManager.unregisterListener(this ); } @Override public void onSensorChanged (SensorEvent event) { float [] values = event.values; int sensorType = event.sensor.getType(); StringBuilder stringBuilder = null ; if (sensorType == Sensor.TYPE_LIGHT){ stringBuilder = new StringBuilder (); stringBuilder.append("光的强度值" ); stringBuilder.append(values[0 ]); textLIGHT.setText(stringBuilder.toString()); } } @Override public void onAccuracyChanged (Sensor sensor, int accuracy) { } }
磁场传感器
我们手机的磁场传感器可以获取在x、y、z方向上的磁场强度。
使用磁场传感器实现指南针
案例在作者的手机上出现闪退且无法运行,因此代码仅供参考。
若找到解决方式请联系作者,一起学习交流。
需要准备一张表示指南针的图片,命名为compass,放置于res/drawable下。
自定义View类PointerView.class,实现指针绘制:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public class PointerView extends View implements SensorEventListener { private SensorManager sensorManager; private Bitmap pointer = null ; private float [] allValues; public PointerView (Context context, @Nullable AttributeSet attrs) { super (context, attrs); sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); sensorManager.registerListener(this , sensorManager .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), sensorManager.SENSOR_DELAY_GAME); pointer = BitmapFactory.decodeResource(super .getResources(), R.drawable.compass); } @Override public void onSensorChanged (SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { float [] value = event.values; allValues = value; super .postInvalidate(); } } @Override public void onAccuracyChanged (Sensor sensor, int accuracy) { } @Override protected void onDraw (Canvas canvas) { super .onDraw(canvas); if (allValues != null ) { float x = allValues[0 ]; float y = allValues[1 ]; canvas.restore(); canvas.translate(super .getWidth() / 2 , super .getHeight() / 2 ); if (y == 0 && x > 0 ) { canvas.rotate(90 ); } else if (y == 0 && x < 0 ) { canvas.rotate(270 ); } else { if (y >= 0 ) { canvas.rotate((float ) Math.tanh(x / y) * 90 ); } else { canvas.rotate(180 + (float ) Math.tanh(x / y) * 90 ); } } canvas.drawBitmap(this .pointer, -this .pointer.getWidth() / 2 , -this .pointer.getHeight() / 2 , new Paint ()); } } }
编写activity_main.xml布局资源文件,自定义界面:
1 2 3 4 5 <FrameLayout ... > <com.yang.compass.PointerView android:layout_width ="wrap_content" android:layout_height ="wrap_content" /> </FrameLayout >
MainActivity.java使用默认即可。
加速度传感器
加速度传感器主要用于测算一些瞬时加速 或减速 的动作。比如:摇一摇、计步等。
手机屏幕向上,当手机横向移动时,会产生X方向的加速度;前后移动,会产生Y方向的加速度;垂直上下移动会产生Z方向的加速度。
实现摇一摇功能
编写activity_main.xml实现程序主界面:
1 2 3 4 5 6 7 8 9 <LinearLayout ... android:gravity ="center" tools:context =".MainActivity" > <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="摇一摇试试?" android:textSize ="40sp" /> </LinearLayout >
编写info.xml界面,实现摇一摇成功后显示的对话框:
1 2 3 4 5 6 7 8 9 <RelativeLayout ... > <TextView android:layout_width ="500dp" android:layout_height ="500dp" android:gravity ="center" android:layout_centerInParent ="true" android:text ="你上当了!" android:textSize ="40sp" /> </RelativeLayout >
编写MainActivity.java实现摇一摇主逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class MainActivity extends AppCompatActivity implements SensorEventListener { private SensorManager sensorManager; private Vibrator vibrator; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE); } @Override protected void onResume () { super .onResume(); sensorManager.registerListener( this ,sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME); } @Override public void onSensorChanged (SensorEvent event) { int sensorType = event.sensor.getType(); if (sensorType == Sensor.TYPE_ACCELEROMETER){ float [] values = event.values; if (values[0 ] > 15 || values[1 ] > 15 || values[2 ] > 20 ){ Toast.makeText(MainActivity.this , "摇一摇" , Toast.LENGTH_SHORT).show(); AlertDialog.Builder alertDialog = new AlertDialog .Builder(this ); alertDialog.setView(R.layout.info); alertDialog.show(); vibrator.vibrate(500 ); sensorManager.unregisterListener(this ); } } } @Override public void onAccuracyChanged (Sensor sensor, int accuracy) { } }
测试: 本案例只能实现摇动一次弹出对话框,无法实现多次摇动弹出对话框。
方向传感器
方向传感器主要用于感应手机的摆放状态。
返回值
它可以返回三个角度:
在Z轴上旋转的角度:手机方向Y轴与地磁场北极方向的角度,当手机绕Z轴旋转时这个值发生变化。
在X轴上旋转的角度:手机底部或尾部翘起的角度,当手机绕X轴时这个值发生变化。
在Y轴上旋转的角度:表示手机左侧或右侧翘起的角度,当手机绕Y轴时这个值发生变化。
使用方向传感器
获取方向传感器:getDefaultSensor(Sensor.TYPE_ORIENTATION)
(新SDK中方法已过期 )
我们可以使用加速度传感器与磁场传感器结合实现这个功能。如下图:
注意:我们使用SensorManager.getOrientation()
得到的 返回值是弧度 ,而不是角度 ,因此我们需要使用Math.toDegrees()
将弧度转换换成角度 。
实现水平仪
步骤
创建自定义View,并实现SenorEventListener接口
布局界面
为磁场传感器和加速度传感器注册监听器,并获取传感器的取值
获取z、x、y轴的旋转角度,并绘制小球。
素材获取:Android利用Sensor(传感器)实现水平仪功能
代码实现
我们需要准备水平仪的仪表盘图片和气泡图标,分别命名为background和bubble,将它们置于res/drawable目录下,素材可以使用上图连接进行获取。
创建自定义View——SpiritlevelView.class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 public class SpiritlevelView extends View implements SensorEventListener { private Bitmap bubble; private Bitmap back; float [] accelerometerValues = new float [3 ]; float [] magneticValues = new float [3 ]; private final int MAX_ANGLE = 30 ; private int bubbleX, bubbleY; public SpiritlevelView (Context context, @Nullable AttributeSet attrs) { super (context, attrs); SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); sensorManager.registerListener(this , sensorManager .getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_GAME); sensorManager.registerListener(this , sensorManager .getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_GAME); bubble = BitmapFactory.decodeResource(getResources(), R.drawable.bubble); } @Override public void onSensorChanged (SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { accelerometerValues = event.values.clone(); } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) { magneticValues = event.values.clone(); } float [] R = new float [9 ]; float [] values = new float [3 ]; SensorManager.getRotationMatrix(R, null , accelerometerValues, magneticValues); SensorManager.getOrientation(R, values); float xAngle = (float ) Math.toDegrees(values[1 ]); float yAngle = (float ) Math.toDegrees(values[2 ]); getPosition(xAngle, yAngle); super .postInvalidate(); } @Override public void onAccuracyChanged (Sensor sensor, int accuracy) { } private void getPosition (float xAngle, float yAngle) { int x = (super .getWidth() - bubble.getWidth()) / 2 ; int y = (super .getHeight() - bubble.getHeight()) / 2 ; if (Math.abs(yAngle) <= MAX_ANGLE) { int deltaX = (int ) ((super .getWidth() - bubble.getWidth()) / 2 * yAngle / MAX_ANGLE); x -= deltaX; } else if (yAngle > MAX_ANGLE) { x = 0 ; } else { x = super .getWidth() - bubble.getWidth(); } if (Math.abs(xAngle) <= MAX_ANGLE) { int deltaY = (int ) ((super .getHeight() - bubble.getHeight()) / 2 * xAngle / MAX_ANGLE); y += deltaY; } else if (xAngle > MAX_ANGLE) { y = super .getHeight() - bubble.getHeight(); } else { y = 0 ; } bubbleX = x; bubbleY = y; } @Override protected void onDraw (Canvas canvas) { super .onDraw(canvas); canvas.drawBitmap(bubble,bubbleX,bubbleY,new Paint ()); } }
编写activity_main.xml布局界面:
1 2 3 4 5 6 7 8 9 10 <FrameLayout ... > <ImageView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_gravity ="center" android:src ="@drawable/background" /> <com.yang.gradienter.SpiritlevelView android:layout_width ="match_parent" android:layout_height ="match_parent" /> </FrameLayout >
MainActivity.java使用默认即可。
位置服务与地图应用
获取LocationProvider
LocationProvider是位置源的意思,用于提供定位 信息。
常见的LocationProvider:GPS、network、passive
获取LocationProvider方法
获取所有可用的LocationProvider:LocationManager对象的getAllProviders()
方法
通过名称获得LocationProvider:LocationManager对象的getProvider()
方法
通过Criteria类获得LocationProvider
我们根据代码来进行方法的测试:
编写布局资源文件activity_main.xml对页面进行布局:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <RelativeLayout ... > <TextView android:id ="@+id/title" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:text ="可用LocationProvider" android:textColor ="#257678" android:textSize ="26sp" android:textStyle ="bold" /> <TextView android:id ="@+id/provider" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:textColor ="#0B80DD" android:lineSpacingExtra ="18sp" android:layout_centerInParent ="true" android:textStyle ="bold" android:textSize ="18sp" /> </RelativeLayout >
编写MainActivity.java实现获取LocationProvider的三种方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class MainActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.provider); LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); Criteria criteria = new Criteria (); criteria.setCostAllowed(false ); criteria.setAccuracy(Criteria.ACCURACY_FINE); criteria.setPowerRequirement(Criteria.POWER_LOW); String provider = locationManager.getBestProvider(criteria,true ); textView.setText(provider); } }
在本次案例中我们获取GPS信息,因此我们需要获取GPS的权限 。
对AndroidManifest.xml进行修改:
1 2 3 4 5 6 7 8 9 <manifest ... > <uses-permission android:name ="android.permission.ACCESS_FINE_LOCATION" /> <application ... android:requestLegacyExternalStorage ="true" > <activity android:name =".MainActivity" > ... </activity > </application > </manifest >
同时我们还需要在模拟器内部授予本案例的应用读取位置信息(定位)的权限!
获取定位信息
获取定位信息的步骤
获取系统的LocationManager对象:getSystemService(LOCATION_SERVICE)
设置一个监听器:LocationManager对象的requestLocationUpdate()
方法
获取最近的定位信息:LocationManager的getLastKnownLocation()
方法
编写布局资源文件activity_main.xml对页面进行布局:
1 2 3 4 5 6 7 8 9 10 <RelativeLayout ... > <TextView android:id ="@+id/location" android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:layout_centerInParent ="true" android:textSize ="18sp" android:textStyle ="bold" android:textColor ="#06518C" /> </RelativeLayout >
编写MainActivity.java实现获取定位信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 public class MainActivity extends AppCompatActivity { private TextView textView; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.location); LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (ActivityCompat.checkSelfPermission(this , Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this , Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return ; } locationManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 1000 , 1 , new LocationListener () { @Override public void onLocationChanged (Location location) { } @Override public void onStatusChanged (String provider, int status, Bundle extras) { } @Override public void onProviderEnabled (String provider) { } @Override public void onProviderDisabled (String provider) { } } ); Location location = locationManager. getLastKnownLocation(LocationManager.GPS_PROVIDER); locationUpdates(location); } public void locationUpdates (Location location) { if (location != null ){ StringBuilder stringBuilder = new StringBuilder (); stringBuilder.append("您的位置是:\n" ); stringBuilder.append("经度:" ); stringBuilder.append(location.getLongitude()); stringBuilder.append("\n纬度:" ); stringBuilder.append(location.getLatitude()); textView.setText(stringBuilder.toString()); }else { textView.setText("没有获取到GPS信息" ); } } }
在本次案例中我们获取GPS信息,因此我们需要获取GPS的权限 。
对AndroidManifest.xml进行修改:
1 2 3 4 5 6 7 8 9 10 <manifest ... > <uses-permission android:name ="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name ="android.permission.ACCESS_FINE_LOCATION" /> <application ... android:requestLegacyExternalStorage ="true" > <activity android:name =".MainActivity" > ... </activity > </application > </manifest >
同时我们还需要在模拟器内部授予本案例的应用读取位置信息(定位)的权限!
应用百度地图API
百度地图API:一套为开发者免费 使用的基于百度地图的应用程序接口。它提供了定位服务、地图服务、数据服务、出行服务、鹰眼轨迹服务、分析服务等服务。
准备工作
新版网址在网页最下方,点击“立即注册”进入申请注册。
注册成功后创建应用,应用类型选择Android SDK,启动服务选择默认。
然后获取发布版SHA1 ,你需要找到你电脑SDK或AVD目录下有个名为.android的目录,**复制当前文件的位置!**比如:D:/avd/.android 就复制这个目录。
如何确定.android目录:在这个目录下有个名为debug.keystore的文件。
然后我们进入AS,进入Terminal面板,切换到刚刚复制的目录中,然后输入:
1 keytool -list -v -keystore debug.keystore -alias androiddebugkey
点击回车后,会让你输入秘钥库口令,一般默认都是android。输入的形式是不回显的。
密码输入成功后,我们可以找到证书指纹 ,里面就有SHA1,我们复制填写即可。
然后我们还需要填写PackageName ,这个值你可以随意填写,但是!你编写的应用的Java代码得放在你填写的这个包目录下。
SHA1和包名会自动构成安全码,我们填写好信息提交就可以了。提交成功后会创建一个应用,应用里面有访问应用(AK ) ,这个值就是开发秘钥 ,它在我们编写代码时有用。
到此,我们就成功申请了秘钥 了。
进入网址后,开发文档 > Android地图 SDK > 产品下载 > 自定义下载,选择你需要jar包开发资源。
我在此选择 全量定位、基础地图、检索功能、LBS云检索、计算工具、驾车导航(含TTS)、全景图功能,选择后,点击下方 “开发包” 进行下载。
到此,我们的准备工作就完成了,接下来就该应用百度地图API显示百度地图了。
应用百度地图API显示地图
步骤
配置百度Android地图API
布局界面
初始化SDK应用的Context全局变量
管理地图生命周期
具体实现
本文未概述清楚的地方请参考:
Android使用百度地图API 利用AS 3.0对于百度地图API的开发
运行应用进行测试时,使用真机测试,真机需要联网!
配置百度地图API:
在AS中将项目切换成project模式。首先找到我们刚下载的 百度LBS Android SDK 然后进行解压,解压成功后如图:
我们只使用圈起来的libs目录。打开这个目录,将这个目录下的jar包复制到我们项目中libs目录(AS中)下,然后选中这些jar包,右击,Add As Library,把这些jar包添加到类库中。
在我们项目src/main/目录下(AS中)新建jniLibs目录,把libs目录下的五个文件夹复制进去,即:
刚刚复制的jar包就是上图中的那两个。
代码编写: ==你编写的应用的Java代码必须放在你申请秘钥时填写的包名目录下。==比如,我申请秘钥时填写的包名是com.yang,因此我将我的Java代码必须放在这个包下。
编写activity_main.xml布局界面:
1 2 3 4 5 6 7 <RelativeLayout ... > <com.baidu.mapapi.map.MapView android:id ="@+id/bmapview" android:layout_width ="match_parent" android:layout_height ="match_parent" android:clickable ="true" /> </RelativeLayout >
在AndroidManifest.xml中指定开发秘钥、设置权限:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <manifest ... > <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" /> <uses-permission android:name ="android.permission.WRITE_SETTINGS" tools:ignore ="ProtectedPermissions" /> <uses-permission android:name ="android.permission.CAMERA" /> <uses-permission android:name ="android.permission.READ_PHONE_STATE" /> <uses-permission android:name ="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name ="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name ="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name ="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name ="android.permission.CHANGE_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.INTERNET" /> <uses-permission android:name ="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" tools:ignore ="ProtectedPermissions" /> <uses-permission android:name ="android.permission.WAKE_LOCK" /> <application ... android:requestLegacyExternalStorage ="true" > <meta-data android:name ="com.baidu.lbsapi.API_KEY" android:value ="WVbGmRg0YKTz7FEjiVy3H3lgBepGp0rZ" > </meta-data > <activity android:name =".MainActivity" > ... </activity > </application > </manifest >
开发秘钥在<application>
标签内指定,使用<meta-data>
进行指定。其中,name为固定值,即:com.baidu.lbsapi.API_KEY ;value为你申请的秘钥 。
编写MainActivity.java初始化地图应用、管理地图生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class MainActivity extends AppCompatActivity { private MapView mMapView; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); SDKInitializer.initialize(getApplicationContext()); setContentView(R.layout.activity_main); mMapView = findViewById(R.id.bmapview); } @Override protected void onResume () { super .onResume(); mMapView.onResume(); } @Override protected void onPause () { super .onPause(); mMapView.onPause(); } @Override protected void onDestroy () { super .onDestroy(); mMapView.onDestroy(); mMapView = null ; } }
到此,我们并没有全部完成。如果我们就这样去真机上测试,大概率无法进入界面,会直接闪退。
我们需要在创建一个继承至Application的java类,我在此创建MyApplication.java:
1 2 3 4 5 6 7 public class MyApplication extends Application { @Override public void onCreate () { SDKInitializer.initialize(this ); super .onCreate(); } }
这下,我们是真的完成了代码的编写。
我们可以进入真机测试阶段,但是一定记得要将手机联网,否则无法运行!
定位到我的位置
定位到我的位置的步骤
实现在百度地图API上定位我的位置
准备:准备一张定位图标图片资源(也可以不准备,使用默认),将其命名为loc,置于res/drawable目录下。
本案例在 上述应用百度地图API显示地图 的案例 中进行修改 !
布局资源文件activity_main.xml不变,自定义类MyApplication.java不变。
在AndroidManifest.xml中添加两条权限,用于获取GPS定位服务:
1 2 <uses-permission android:name ="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name ="android.permission.ACCESS_FINE_LOCATION" />
修改MainActivity.java,实现定位服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 public class MainActivity extends AppCompatActivity { private MapView mMapView; private BaiduMap mBaiduMap; private boolean isFirstLoc = true ; private MyLocationConfiguration.LocationMode locationMode; @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); SDKInitializer.initialize(getApplicationContext()); setContentView(R.layout.activity_main); mMapView = findViewById(R.id.bmapview); mBaiduMap = mMapView.getMap(); LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); if (ActivityCompat.checkSelfPermission(this , Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this , Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return ; } locationManager.requestLocationUpdates( locationManager.GPS_PROVIDER, 1000 , 1 , new LocationListener () { @Override public void onLocationChanged (Location location) { locationUpdates(location); } @Override public void onStatusChanged (String provider, int status, Bundle extras) { } @Override public void onProviderEnabled (String provider) { } @Override public void onProviderDisabled (String provider) { } } ); Location location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); locationUpdates(location); } @Override protected void onResume () { super .onResume(); mMapView.onResume(); } @Override protected void onPause () { super .onPause(); mMapView.onPause(); } @Override protected void onDestroy () { super .onDestroy(); mMapView.onDestroy(); mMapView = null ; } @Override protected void onStart () { super .onStart(); mBaiduMap.setMyLocationEnabled(true ); } @Override protected void onStop () { super .onStop(); mBaiduMap.setMyLocationEnabled(false ); } public void locationUpdates (Location location) { if (location != null ) { LatLng ll = new LatLng (location.getLatitude(), location.getLongitude()); Log.i("Location" , "纬度:" + location.getLatitude() + "|经度:" + location.getLongitude()); if (isFirstLoc) { MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(ll); mBaiduMap.animateMapStatus(u); isFirstLoc = false ; } MyLocationData locationData = new MyLocationData .Builder().accuracy(location.getAccuracy()) .direction(100 ) .latitude(location.getLatitude()) .longitude(location.getLongitude()) .build(); mBaiduMap.setMyLocationData(locationData); BitmapDescriptor bitmapDescriptor = BitmapDescriptorFactory.fromResource(R.drawable.loc); locationMode = MyLocationConfiguration.LocationMode.NORMAL; MyLocationConfiguration config = new MyLocationConfiguration (locationMode, true , bitmapDescriptor); mBaiduMap.setMyLocationConfiguration(config); } else { Log.i("Location" , "没有获取到GPS信息" ); } } }
测试要点:使用真机测试,打开位置服务及权限,真机需要联网,尽量在空旷区域、而不是室内进行测试。
Android传感器及LBS完