(1)界面布局activity_main.xml代码:包含一个id为tv的TextView控件,用于显示定位结果(经纬度)
(2)配置权限:
<!-- 2个定位权限是危险权限并处于一个权限组,需要动态申请 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/><!--精确定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/><!--粗糙定位-->
<!-- 网络权限和WiFi权限是普通权限,不需要动态申请 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/><!--网络状态-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/><!--WiFi状态-->
(3)界面程序MainActivity.java架构及代码如下:
/*
Android提供了三种定位方式(GPS定位、WiFI定位和基站定位)获得定位信息—经纬度【基站定位也称移动网络定位,也称为GPRS定位】
打开位置服务时,必须从三种定位模式(高精度—混合定位、节电—网络定位和单独的GPS定位)中选择一种,通常选择混合定位
GPS定位精度高,但可能由于GPS信号弱而较慢甚至获取不到
GPS定位对应于权限android.permission.ACCESS_FINE_LOCATION
网络定位(WiFi或移动网络)定位速度快,但精度相对GPS低
网络定位对应于权限android.permission.ACCESS_COARSE_LOCATION【COARSE系粗糙之意】
*/
public class MainActivity extends AppCompatActivity {
LocationManager lm; //位置服务管理器
ConnectivityManager cm; //网络连接管理器
WifiManager wfm; //Wifi管理器
TextView tv; //显示经纬度
final static int LOCATION_SETTING_REQUEST_CODE = 100;
final static int NETWORK_SETTING_REQUEST_CODE = 200;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//如果没有ACCESS_COARSE_LOCATION权限,动态请求用户允许使用该权限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 1);
}else {
prepareLocatingService();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case 1:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { //危险权限
prepareLocatingService();
} else {
Toast.makeText(this, "没有授予定位权限!", Toast.LENGTH_LONG).show();
finish();
}
}
}
//定位服务预备
void prepareLocatingService() {
tv = findViewById(R.id.tv);
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
//android API 24之后,必须使用 getApplicationContext()
wfm = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
//打开定位服务时(有多种检测方法)
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) || lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
//打开位置服务作为定位的入口
locatingService(); //方法调用
} else {
new AlertDialog.Builder(this)
.setIcon(R.mipmap.ic_launcher)
.setTitle("消息框")
.setMessage("请先打开定位服务!")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//定位服务设置意图
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
//有返回值的调用,设置定位设置请求码
startActivityForResult(intent, LOCATION_SETTING_REQUEST_CODE);
}
})
.show();
Log.i("wustwzxabc", "test1111"); //未阻塞,即用户单击“确定”按钮前此信息已经输出
//即Android里的AlertDialog,是非阻塞的!
}
}
void locatingService() { //已开启位置服务时
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER) && lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
//使用混合定位(GPS+网络)
if (cm.getActiveNetworkInfo() != null) {
networkLocation(); //为了尽快获取定位数据,假定网络定位优先
} else {
GPSLocation(); //使用GPS定位
}
} else {
if (lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) { //使用单GPS定位方式
GPSLocation();
} else {
if (lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { //未开启GPS定位—即网络定位—节电模式
networkLocation();
}
}
}
}
void GPSLocation() {
tv.setText("GPS定位中...");
Toast.makeText(getApplicationContext(), "GPS定位", Toast.LENGTH_LONG).show();
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, new LocationListener() {
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
String string1 = "纬度为:" + location.getLatitude() + "\n经度为:" + location.getLongitude();
tv.setText(string1);
}
});
}
void networkLocation() {
if (cm.getActiveNetworkInfo() != null) { //有网络连接时
if (wfm.isWifiEnabled()) { //WIFI有效时
Toast.makeText(getApplicationContext(), "WiFi方式的网络定位", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getApplicationContext(), "基站方式的网络定位", Toast.LENGTH_LONG).show();
}
} else { //没有网络连接时
new AlertDialog.Builder(this)
.setIcon(R.mipmap.ic_launcher)
.setTitle("消息框")
.setMessage("无网络连接!请先设置一种网络连接...")
.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//进入网络连接设置
Intent intent = new Intent(Settings.ACTION_SETTINGS);
//有返回值的调用,设置网络设置请求码
startActivityForResult(intent, NETWORK_SETTING_REQUEST_CODE);
}
})
.show();
}
//下面的请求位置(实时)更新,Android 6.0及以上版本需要在首次运行时动态加载上述权限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000, 1, new LocationListener() { //实时监听
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
// TODO Auto-generated method stub
}
@Override
public void onProviderEnabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onProviderDisabled(String arg0) {
// TODO Auto-generated method stub
}
@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
String string2 = "纬度为:" + location.getLatitude() + "\n经度为:" + location.getLongitude();
//Toast.makeText(getApplicationContext(), string2, Toast.LENGTH_LONG).show();
tv.setText(string2);
}
});
}
@Override //有返回值的调用
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//只用到了请求码
if (requestCode == LOCATION_SETTING_REQUEST_CODE || requestCode == NETWORK_SETTING_REQUEST_CODE) {
prepareLocatingService();
}
}
}
运行效果
预备:访问http://lbsyun.baidu.com,依次选择:开发文档->Android 地图SDK->产品下载->自定义下载,勾选百度定位包后下载、解压
在项目里,新建名为example10_2的模块
选择模块视图为Project,复制定位包BaiduLBS_Android.jar至模块example10 _2的libs文件夹里,然后右键jar文件,选择“Add As Library”
在main文件夹下新建名为jniLibs的文件夹,复制存放.so文件(share object)的多个文件夹至jniLibs文件夹
在模块的清单文件里,增加如下权限:
<!--百度定位所需要权限,前面2个是LOCATE权限组的2个危险权限-->
<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.INTERNET"/> <!--因为程序要与百度云服务交互-->
获取本机的Android指纹码——SHA(Secure Hash Algorithm,安全散列算法),其方法如下:
访问该网址 进入百度地图开发者页面、注册和登录(注册含于登录界面里)
使用百度帐号成功登录后,进入控制台,创建应用
提交后,生成应用的AK,查看应用Key并复制,以供清单文件配置应用Key用。
在清单文件里,在Activity组件注册的代码后,添加注册远程服务和配置应用Key的代码:
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote"/>
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="NDnYRd8LK85vGbLeRVaV23x9RccY5M3p"/><!--应用Key是在百度开发者页面里生成的,需要替换-->
布局activitymain.xml代码:添加一个id为tvpositionText的TextView控件
界面程序MainActivity.java代码如下:
/*
百度定位信息,使用一个TextView控件显示
一般需要打开定位服务,选择高精度定位模式,有网络连接
需要在清单文件里使用百度云服务(参见清单文件service标签)
需要创建应用(模块)的Key,并写入清单文件(参见清单文件meta标签)
*/
public class MainActivity extends AppCompatActivity {
public LocationClient mLocationClient; //定位客户端
TextView tv_positionText; //显示定位信息控件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//如果没有定位权限,动态请求用户允许使用该权限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}else {
requestLocation();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "没有定位权限!", Toast.LENGTH_LONG).show();
finish();
} else {
requestLocation();
}
}
}
private void requestLocation() {
initLocation(); //初始化
mLocationClient.start(); //开始定位
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocationClient.stop();
}
private void initLocation() {
setContentView(R.layout.activity_main);
mLocationClient = new LocationClient(getApplicationContext());
mLocationClient.registerLocationListener(new MyLocationListener());
tv_positionText = findViewById(R.id.tv_positionText);
//定位客户端操作
LocationClientOption option = new LocationClientOption();
//设置扫描时间间隔(单位:毫秒)
option.setScanSpan(1000);
//设置定位模式,三选一
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
/*option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving);
option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);*/
//设置需要地址信息
option.setIsNeedAddress(true);
//保存定位参数
mLocationClient.setLocOption(option);
}
class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
StringBuffer currentPosition = new StringBuffer();
currentPosition.append("Longitude:").append(bdLocation.getLongitude()).append("\n");
currentPosition.append("Latitude:").append(bdLocation.getLatitude()).append("\n");
currentPosition.append("Country:").append(bdLocation.getCountry()).append("\n");
currentPosition.append("Province:").append(bdLocation.getProvince()).append("\n");
currentPosition.append("City:").append(bdLocation.getCity()).append("\n");
currentPosition.append("District:").append(bdLocation.getDistrict()).append("\n");
currentPosition.append("Street:").append(bdLocation.getStreet()).append("\n");
currentPosition.append("Address:").append(bdLocation.getAddrStr());
tv_positionText.setText(currentPosition);
}
}
}
运行效果
在项目里,新建名为example10_3的模块,并切换至Project视图
访问http://lbsyun.baidu.com,依次选择:开发文档->Android开发->Android地图SDK->产品下载,勾选百度定位包和百度地图后下载、解压,按照上一模块的做法,复制.jar文件到libs文件夹,新建jniLibs文件夹并复制包含.so文件的几个文件夹(需要进入jniLibs文件夹,使用Windows文件资源管理器复制,其容量应为18M左右!)
生成本应用的Key。
在清单文件里,在Activity组件注册的代码后,添加注册远程服务和配置应用Key的代码:
<service android:name="com.baidu.location.f" android:enabled="true" android:process=":remote"/>
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="AXHLWlI2UtWhLk2YMGaLSdzva3WfhOyK"/><!--应用Key是在百度开发者页面里生成的,需要替换-->
界面布局使用帧布局,包含有重叠效果的地图和位置文本,activity_main.xml的完整代码如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!--百度地图控件-->
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
<!--位置文本布局的背景色代码的前2位代码为透明度-->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#e0000000"
android:orientation="vertical" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="20dp"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="纬度:"
android:textColor="#ffffff"
android:textSize="15dp" />
<TextView
android:id="@+id/tv_Lat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="#ffffff"
android:textSize="15dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="经度:"
android:textColor="#ffffff"
android:textSize="15dp" />
<TextView
android:id="@+id/tv_Lon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="#ffffff"
android:textSize="15dp" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="10dp"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="地址:"
android:textColor="#ffffff"
android:textSize="15dp" />
<TextView
android:id="@+id/tv_Add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:textColor="#ffffff"
android:textSize="15dp" />
</LinearLayout>
</LinearLayout>
</FrameLayout>
界面程序MainActivity.java代码如下:
/*
百度地图应用,包含定位信息和地图显示
一般需要打开定位服务,选择高精度定位模式,有网络连接
需要在清单文件里使用百度云服务(参见清单文件service标签)
需要创建应用(模块)的Key,并写入清单文件(参见清单文件meta标签)
*/
public class MainActivity extends AppCompatActivity {
LocationClient mLocationClient; //定位客户端
MapView mapView; //Android Widget地图控件
BaiduMap baiduMap;
boolean isFirstLocate = true;
TextView tv_Lat; //纬度
TextView tv_Lon; //经度
TextView tv_Add; //地址
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//如果没有定位权限,动态请求用户允许使用该权限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}else {
requestLocation();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "没有定位权限!", Toast.LENGTH_LONG).show();
finish();
} else {
requestLocation();
}
}
}
private void requestLocation() {
initLocation();
mLocationClient.start();
}
private void initLocation() { //初始化
mLocationClient = new LocationClient(getApplicationContext());
mLocationClient.registerLocationListener(new MyLocationListener());
SDKInitializer.initialize(getApplicationContext());
setContentView(R.layout.activity_main);
mapView = findViewById(R.id.bmapView);
baiduMap = mapView.getMap();
tv_Lat = findViewById(R.id.tv_Lat);
tv_Lon = findViewById(R.id.tv_Lon);
tv_Add = findViewById(R.id.tv_Add);
LocationClientOption option = new LocationClientOption();
//设置扫描时间间隔
option.setScanSpan(1000);
//设置定位模式,三选一
option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
/*option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving);
option.setLocationMode(LocationClientOption.LocationMode.Device_Sensors);*/
//设置需要地址信息
option.setIsNeedAddress(true);
//保存定位参数
mLocationClient.setLocOption(option);
}
//内部类,百度位置监听器
private class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation bdLocation) {
tv_Lat.setText(bdLocation.getLatitude()+"");
tv_Lon.setText(bdLocation.getLongitude()+"");
tv_Add.setText(bdLocation.getAddrStr());
if(bdLocation.getLocType()==BDLocation.TypeGpsLocation || bdLocation.getLocType()==BDLocation.TypeNetWorkLocation){
navigateTo(bdLocation);
}
}
}
private void navigateTo(BDLocation bdLocation) {
if(isFirstLocate){
LatLng ll = new LatLng(bdLocation.getLatitude(),bdLocation.getLongitude());
MapStatusUpdate update = MapStatusUpdateFactory.newLatLng(ll);
baiduMap.animateMapStatus(update);
isFirstLocate = false;
}
}
@Override
protected void onResume() {
super.onResume();
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mapView.onResume();
}
@Override
protected void onDestroy() {
super.onDestroy();
mLocationClient.stop();
mapView.onDestroy();
}
}