第一步、Android使用谷歌地图权限
Android上使用谷歌地图
必备条件:、Android设备上安装Google Play Service
由于谷歌在国内已经被墙了,所以我们只能使用软件使用谷歌地图,而使用谷歌地图的同时,我们需要安装Google Play Service,这个之后用google浏览器下载就行了。
接下来是简单的教程:
1、注册账号并登录 https://code.google.com/apis/console/
2、创建项目并选择项目、点击凭据
3、创建凭据、需要提供包名和AS的SHA1指纹证书
AS的SHA1的指纹证书,可以通过命令行打印,在命令行进入jdk的目录,输入:
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
结果如下
最后、保存、将生成的key值写进谷歌地图工程的配置文件中,如下
第二步、开发基于谷歌的地理围栏功能
1、相关权限
以上三个权限为定位和加载地图所用
2、注册监听地理围栏服务
3、创建地理围栏管理器
public class GeofenceManager implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback, LocationListener {
private static final String TAG = "Dan";
private static GoogleApiClient googleApiClient;
private static GeofenceManager _singleInstance;
GeofencingClient geofencingClient;
private static Context appContext;
private static final String ERR_MSG = "Application Context is not set!! " +
"Please call GeofenceSngleton.init() with proper application context";
private PendingIntent mGeofencePendingIntent;
private static ArrayList mGeofenceList;
private GeofenceManager() {
if (appContext == null)
throw new IllegalStateException(ERR_MSG);
this.googleApiClient = new GoogleApiClient.Builder(this.appContext)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
this.googleApiClient.connect();
geofencingClient = LocationServices.getGeofencingClient(appContext);
mGeofenceList = new ArrayList();
}
public static void init(Context applicationContext) {
appContext = applicationContext;
}
public static GeofenceManager getInstance() {
if (_singleInstance == null)
synchronized (GeofenceManager.class) {
if (_singleInstance == null)
_singleInstance = new GeofenceManager();
}
return _singleInstance;
}
@Override
public void onConnected(Bundle bundle) {
createLocationRequest();
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
//添加地理围栏
public void addGeofence(GeofenceInfo geofenceInfo) {
mGeofenceList.add(new Geofence.Builder()
.setRequestId(geofenceInfo.getUid())
.setCircularRegion(
geofenceInfo.getLatitude(),
geofenceInfo.getLongitude(),
geofenceInfo.getRadius()
)
.setExpirationDuration(5000000)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | Geofence.GEOFENCE_TRANSITION_EXIT)
.build());
}
/**
* 构建地理围栏请求
* */
private GeofencingRequest getGeofencingRequest() {
GeofencingRequest.Builder builder = new GeofencingRequest.Builder();
builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER);
builder.addGeofences(mGeofenceList);
return builder.build();
}
/**
* 返回地理围栏监听服务的Intent
* */
private PendingIntent getGeofencePendingIntent() {
if (mGeofencePendingIntent != null) {
return mGeofencePendingIntent;
}
Intent intent = new Intent(appContext, GeofenceIntentService.class);
return PendingIntent.getService(appContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public void startGeofencing() {
if (!googleApiClient.isConnected()) {
Log.i(TAG,"无法连接谷歌服务");
return;
}
if(checkPermission())
geofencingClient.addGeofences(getGeofencingRequest(), getGeofencePendingIntent()).addOnSuccessListener(new OnSuccessListener() {
@Override
public void onSuccess(Void aVoid) {
Log.i(TAG,"add success");
Log.i(TAG,"地理围栏服务开启");
}
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.i(TAG,"add fail");
}
});
}
public static boolean checkPermission(){
if (ActivityCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return false;
}
return true;
}
public void removeGeofence() {
geofencingClient.removeGeofences(getGeofencePendingIntent());
}
@Override
public void onResult(Status status) {
if (status.isSuccess()) {
Log.i(TAG,"执行地理围栏服务");
} else {
Log.i(TAG,"地理围栏服务错误");
}
}
public static long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
UPDATE_INTERVAL_IN_MILLISECONDS / 2;
public LocationRequest mLocationRequest;
/**
* 创建位置请求对象mLocationRequest,封装监听参数
*/
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
if(checkPermission())
LocationServices.GeofencingApi.addGeofences(googleApiClient, getGeofencingRequest(), getGeofencePendingIntent()).setResultCallback(this);
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
startLocationUpdates();
}
/**
* 开始监听位置变化
*/
protected void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, mLocationRequest, this);
}
@Override
public void onLocationChanged(Location location) {
}
}
各个函数模块都有注释,不做赘述
3、主Activity调用类
public class MainActivity extends AppCompatActivity
implements
OnMyLocationButtonClickListener,
OnMyLocationClickListener,
OnMapReadyCallback,
GoogleMap.OnMapClickListener,
ActivityCompat.OnRequestPermissionsResultCallback {
private static final String TAG = "Dan";
private static final int LOCATION_PERMISSION_REQUEST_CODE = 202;
private GoogleMap mMap;
private GeofenceManager geofenceManager;
private EditText etGeoLatitude,etGeoLongitude,etGeoArea,etGeoRefresh;
private String strGgeoLatitude,strGeoLongitude,strGeoArea,strGeoRefresh;
private Button btnGeoSubmit;
private boolean mPermissionDenied = false;
private static final double DEFAULT_RADIUS_METERS = 100;
private GeofenceInfo geofenceInfo;
private List mCircles = new ArrayList<>(1);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SupportMapFragment mapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
initData();
doTrans();
}
public void initData(){
etGeoLongitude = findViewById(R.id.geo_longitude);
etGeoLatitude = findViewById(R.id.geolatitude);
etGeoArea = findViewById(R.id.geo_area);
etGeoRefresh = findViewById(R.id.geo_refresh);
btnGeoSubmit = findViewById(R.id.geo_submit);
}
public void doTrans(){
btnGeoSubmit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
strGeoLongitude = etGeoLongitude.getText().toString();
strGgeoLatitude = etGeoLatitude.getText().toString();
strGeoArea = etGeoArea.getText().toString();
strGeoRefresh = etGeoRefresh.getText().toString();
geofenceInfo = new GeofenceInfo(Double.parseDouble(strGeoLongitude),Double.parseDouble(strGgeoLatitude),Integer.parseInt(strGeoArea));
DraggableCircle circle = new DraggableCircle(new LatLng(geofenceInfo.getLatitude(),geofenceInfo.getLongitude()), geofenceInfo.getRadius());
mCircles.add(circle);
geofenceManager.addGeofence(geofenceInfo);
geofenceManager.startGeofencing();
}
});
}
/**
*添加地理围栏
* */
public void startNewGeofence(GeofenceInfo geofenceInfo){
DraggableCircle circle = new DraggableCircle(new LatLng(geofenceInfo.getLongitude(),geofenceInfo.getLatitude()), geofenceInfo.getRadius());
mCircles.add(circle);
Location geofenceCenter = new Location("");
geofenceCenter.setLatitude(geofenceInfo.getLatitude());
geofenceCenter.setLongitude(geofenceInfo.getLongitude());
GeofenceManager.init(this);
geofenceManager = GeofenceManager.getInstance();
geofenceManager.addGeofence(geofenceInfo);
geofenceManager.startGeofencing();
}
/**
* 地图加载准备
* */
@Override
public void onMapReady(GoogleMap map) {
mMap = map;
mMap.setOnMyLocationButtonClickListener(this);
mMap.setOnMyLocationClickListener(this);
mMap.setOnMapClickListener(this);
enableMyLocation();
geofenceInfo = new GeofenceInfo(114.00043174,22.5964144312,1);
startNewGeofence(geofenceInfo);
}
/**
* 确认获取定位权限
*/
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
XPermission.requestPermissions(this, LOCATION_PERMISSION_REQUEST_CODE,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, new XPermission.OnPermissionListener() {
@Override
public void onPermissionGranted() {
}
@Override
public void onPermissionDenied() {
XPermission.showTipsDialog(MainActivity.this);
}
});
} else if (mMap != null) {
mMap.setMyLocationEnabled(true);
}
}
@Override
public boolean onMyLocationButtonClick() {
Log.i(TAG, "MyLocation button clicked");
return false;
}
@Override
public void onMyLocationClick(@NonNull Location location) {
Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG).show();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
return;
}
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
enableMyLocation();
} else {
mPermissionDenied = true;
}
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
if (mPermissionDenied) {
showMissingPermissionError();
mPermissionDenied = false;
}
}
private void showMissingPermissionError() {
XPermission.showTipsDialog(MainActivity.this);
}
@Override
public void onMapClick(LatLng latLng) {
etGeoLongitude.setText(latLng.longitude+"");
etGeoLatitude.setText(latLng.latitude+"");
if(tempCircle != null)
tempCircle.remove();
tempCircle = new DraggableCircle(latLng,0);
}
DraggableCircle tempCircle;
private class DraggableCircle {
private final Marker mCenterMarker;
private final Circle mCircle;
private double mRadiusMeters;
public DraggableCircle(LatLng center, double radiusMeters) {
mRadiusMeters = radiusMeters;
mCenterMarker = mMap.addMarker(new MarkerOptions()
.position(center)
.draggable(true));
mCircle = mMap.addCircle(new CircleOptions()
.center(center)
.radius(radiusMeters)
.strokeWidth(2)
.strokeColor(R.color.colorPrimaryDark)
.fillColor(R.color.colorPrimary)
.clickable(false));
}
public void remove(){
mCenterMarker.remove();
mCircle.remove();
}
public void setStrokePattern(List pattern) {
mCircle.setStrokePattern(pattern);
}
public void setClickable(boolean clickable) {
mCircle.setClickable(clickable);
}
}
private static LatLng toRadiusLatLng(LatLng center, double radiusMeters) {
double radiusAngle = Math.toDegrees(radiusMeters / 6371009) /
Math.cos(Math.toRadians(center.latitude));
return new LatLng(center.latitude, center.longitude + radiusAngle);
}
private static double toRadiusMeters(LatLng center, LatLng radius) {
float[] result = new float[1];
Location.distanceBetween(center.latitude, center.longitude,
radius.latitude, radius.longitude, result);
return result[0];
}
}
4、效果图示例
三、功能开发注意事项
1、一定要确保申请key值得包名和自己Android Studio开发环境得SHA1值是一致的,如果不一致日子里面会有key值不存在的报错
2、由于谷歌在国内被墙了,所以在国内使用地理围栏一定要,而且还要下载谷歌服务,不然会出现地图无法显示、无法定位等异常现象
3、由于大陆采用的定位标准是个国际上定位标准是不一样的,所以谷歌的地位在国内会出现偏移,偏移大概500~1000米,这种现象到香港等地方就变得正常了,当然也可以通过一定的算法转换,让谷歌的地位适应国内的定位
源码下载地址:https://download.csdn.net/download/mldan/11216858