Android 高德地圖的定位功能,以及動態開啟許可權
阿新 • • 發佈:2019-01-30
配置工程
配置AndroidManifest.xml
1、許可權
<!--用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
<!--用於訪問GPS定位-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission >
<!--用於獲取運營商資訊,用於支援提供運營商資訊相關的介面-->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<!--用於訪問wifi網路資訊,wifi資訊會用於進行網路定位-->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
<!--用於獲取wifi的獲取許可權,wifi資訊會用來進行網路定位-->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
<!--用於訪問網路,網路定位需要上網-->
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<!--用於讀取手機當前的狀態-->
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
<!--用於寫入快取資料到擴充套件儲存卡-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<!--用於申請呼叫A-GPS模組-->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"></uses-permission>
<!--用於申請獲取藍芽資訊進行室內定位-->
<uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"></uses-permission>
2.設定高德的key
<!--設定高德地圖的key-->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="您的key" />
<service android:name="com.amap.api.location.APSService" />
3.初始化定位
請在主執行緒中宣告AMapLocationClient類物件,需要傳Context型別的引數。推薦用getApplicationConext()方法獲取全程序有效的context。
//宣告AMapLocationClient類物件
public AMapLocationClient mLocationClient = null;
//宣告定位回撥監聽器
public AMapLocationListener mLocationListener = new AMapLocationListener();
//初始化定位
mLocationClient = new AMapLocationClient(getApplicationContext());
//設定定位回撥監聽
mLocationClient.setLocationListener(mLocationListener);
4.配置引數並啟動定位
建立AMapLocationClientOption物件
AMapLocationClientOption物件用來設定發起定位的模式和相關引數等。
案例效果圖
下面是具體程式碼:
MainActivity
public class MainActivity extends AppCompatActivity {
Button btn;
TextView tv;
/**
* 需要進行檢測的許可權陣列
*/
protected String[] needPermissions = {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE
};
private static final int PERMISSON_REQUESTCODE = 0;
/**
* 判斷是否需要檢測,防止不停的彈框
*/
private boolean isNeedCheck = true;
//宣告AMapLocationClient類物件
public AMapLocationClient mLocationClient = null;
//宣告定位回撥監聽器
//public AMapLocationListener mLocationListener = new AMapLocationListener();
// public AMapLocationListener mLocationListener;
//宣告AMapLocationClientOption物件
public AMapLocationClientOption mLocationOption = new AMapLocationClientOption();
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.btn_get);
tv = (TextView) findViewById(R.id.tv_text);
//初始化定位
initLocation();
//設定定位模式為AMapLocationMode.Hight_Accuracy,高精度模式。
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//定位
//啟動定位
// mLocationClient.startLocation();
//設定引數
// mLocationClient.setLocationOption(getDefaultOption());
Log.e("進入", "點選事件" + "=========================================================================");
//定位監聽器
// mLocationListener = new AMapLocationListener() {
// @Override
// public void onLocationChanged(AMapLocation aMapLocation) {
// //
// Log.e("進入", "回撥" + "=========================================================================");
// if (aMapLocation != null) {
// if (aMapLocation.getErrorCode() == 0) {
// //可在其中解析amapLocation獲取相應內容。
// Log.e("進入", "回撥返回" + "aMapLocation != null=========================================================================");
// aMapLocation.getLocationType();//獲取當前定位結果來源,如網路定位結果,詳見定位型別表
// aMapLocation.getLatitude();//獲取緯度
// aMapLocation.getLongitude();//獲取經度
// aMapLocation.getAccuracy();//獲取精度資訊
// aMapLocation.getAddress();//地址,如果option中設定isNeedAddress為false,則沒有此結果,網路定位結果中會有地址資訊,GPS定位不返回地址資訊。
// aMapLocation.getCountry();//國家資訊
// aMapLocation.getProvince();//省資訊
// aMapLocation.getCity();//城市資訊
// aMapLocation.getDistrict();//城區資訊
// aMapLocation.getStreet();//街道資訊
// aMapLocation.getStreetNum();//街道門牌號資訊
// aMapLocation.getCityCode();//城市編碼
// aMapLocation.getAdCode();//地區編碼
// aMapLocation.getAoiName();//獲取當前定位點的AOI資訊
// aMapLocation.getBuildingId();//獲取當前室內定位的建築物Id
// aMapLocation.getFloor();//獲取當前室內定位的樓層
// // aMapLocation.getGpsStatus();//獲取GPS的當前狀態
// //獲取定位時間
// SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// Date date = new Date(aMapLocation.getTime());
// df.format(date);
// tv.setText(aMapLocation.getAddress());
//
// String s = aMapLocation.getAddress();
// Log.e("定位成功,", "地址" + aMapLocation.getAddress());
//// if (!TextUtils.isEmpty(s)) {
//// stopLocation();
//// }
//
//
// } else {
// //定位失敗時,可通過ErrCode(錯誤碼)資訊來確定失敗的原因,errInfo是錯誤資訊,詳見錯誤碼錶。
// Log.e("AmapError", "location Error, ErrCode:"
// + aMapLocation.getErrorCode() + ", errInfo:"
// + aMapLocation.getErrorInfo());
// }
// }
// }
// };
//開始定位
startLocation();
}
});
}
private void startLocation() {
//根據控制元件的選擇,重新設定定位引數
//resetOption();
// 設定定位引數
mLocationClient.setLocationOption(mLocationOption);
// 啟動定位
mLocationClient.startLocation();
}
private void initLocation() {
//初始化client
mLocationClient = new AMapLocationClient(this.getApplicationContext());
//設定定位引數
mLocationClient.setLocationOption(getDefaultOption());
// 設定定位監聽
mLocationClient.setLocationListener(mLocationListener);
}
/**
* 停止定位
*
* @author
* @since 2.8.0
*/
private void stopLocation() {
// 停止定位
mLocationClient.stopLocation();
}
@Override
protected void onDestroy() {
super.onDestroy();
destroyLocation();
}
private void destroyLocation() {
if (null != mLocationClient) {
mLocationClient.onDestroy();
mLocationClient = null;
mLocationOption = null;
}
}
/**
* 預設的定位引數
*
* @author
* @since 2.8.0
*/
private AMapLocationClientOption getDefaultOption() {
AMapLocationClientOption mOption = new AMapLocationClientOption();
mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可選,設定定位模式,可選的模式有高精度、僅裝置、僅網路。預設為高精度模式
mOption.setGpsFirst(false);//可選,設定是否gps優先,只在高精度模式下有效。預設關閉
//mOption.setHttpTimeOut(30000);//可選,設定網路請求超時時間。預設為30秒。在僅裝置模式下無效
// mOption.setInterval(2000);//可選,設定定位間隔。預設為2秒
mOption.setNeedAddress(true);//可選,設定是否返回逆地理地址資訊。預設是true
// mOption.setOnceLocation(false);//可選,設定是否單次定位。預設是false
mLocationOption.setOnceLocation(true); //獲取一次定位結果:
mOption.setOnceLocationLatest(false);//可選,設定是否等待wifi重新整理,預設為false.如果設定為true,會自動變為單次定位,持續定位時不要使用
AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可選, 設定網路請求的協議。可選HTTP或者HTTPS。預設為HTTP
mOption.setSensorEnable(false);//可選,設定是否使用感測器。預設是false
mOption.setWifiScan(true); //可選,設定是否開啟wifi掃描。預設為true,如果設定為false會同時停止主動重新整理,停止以後完全依賴於系統重新整理,定位位置可能存在誤差
mOption.setLocationCacheEnable(true); //可選,設定是否使用快取定位,預設為true
return mOption;
}
/**
* 定位監聽
*/
AMapLocationListener mLocationListener = new AMapLocationListener() {
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (null != aMapLocation) {
//解析定位結果
String result = Utils.getLocationStr(aMapLocation);
tv.setText(result);
Log.e("定位", "aMapLocation is null" + result);
} else {
tv.setText("定位失敗,aMapLocation is null");
Log.e("定位失敗", "aMapLocation is null");
}
}
};
//----------以下動態獲取許可權---------
@Override
protected void onResume() {
super.onResume();
if (isNeedCheck) {
checkPermissions(needPermissions);
}
}
/**
* 檢查許可權
*
* @param
* @since 2.5.0
*/
private void checkPermissions(String... permissions) {
//獲取許可權列表
List<String> needRequestPermissonList = findDeniedPermissions(permissions);
if (null != needRequestPermissonList
&& needRequestPermissonList.size() > 0) {
//list.toarray將集合轉化為陣列
ActivityCompat.requestPermissions(this,
needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]),
PERMISSON_REQUESTCODE);
}
}
/**
* 獲取許可權集中需要申請許可權的列表
*
* @param permissions
* @return
* @since 2.5.0
*/
private List<String> findDeniedPermissions(String[] permissions) {
List<String> needRequestPermissonList = new ArrayList<String>();
//for (迴圈變數型別 迴圈變數名稱 : 要被遍歷的物件)
for (String perm : permissions) {
if (ContextCompat.checkSelfPermission(this,
perm) != PackageManager.PERMISSION_GRANTED
|| ActivityCompat.shouldShowRequestPermissionRationale(
this, perm)) {
needRequestPermissonList.add(perm);
}
}
return needRequestPermissonList;
}
/**
* 檢測是否說有的許可權都已經授權
*
* @param grantResults
* @return
* @since 2.5.0
*/
private boolean verifyPermissions(int[] grantResults) {
for (int result : grantResults) {
if (result != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode,
String[] permissions, int[] paramArrayOfInt) {
if (requestCode == PERMISSON_REQUESTCODE) {
if (!verifyPermissions(paramArrayOfInt)) { //沒有授權
showMissingPermissionDialog(); //顯示提示資訊
isNeedCheck = false;
}
}
}
/**
* 顯示提示資訊
*
* @since 2.5.0
*/
private void showMissingPermissionDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.notifyTitle);
builder.setMessage(R.string.notifyMsg);
// 拒絕, 退出應用
builder.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
builder.setPositiveButton(R.string.setting,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
startAppSettings();
}
});
builder.setCancelable(false);
builder.show();
}
/**
* 啟動應用的設定
*
* @since 2.5.0
*/
private void startAppSettings() {
Intent intent = new Intent(
Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivity(intent);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
this.finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
}
Utils
public class Utils {
/**
* 開始定位
*/
public final static int MSG_LOCATION_START = 0;
/**
* 定位完成
*/
public final static int MSG_LOCATION_FINISH = 1;
/**
* 停止定位
*/
public final static int MSG_LOCATION_STOP= 2;
public final static String KEY_URL = "URL";
public final static String URL_H5LOCATION = "file:///android_asset/location.html";
/**
* 根據定位結果返回定位資訊的字串
* @param loc
* @return
*/
public synchronized static String getLocationStr(AMapLocation location){
if(null == location){
return null;
}
StringBuffer sb = new StringBuffer();
//errCode等於0代表定位成功,其他的為定位失敗,具體的可以參照官網定位錯誤碼說明
if(location.getErrorCode() == 0){
sb.append("定位成功" + "\n");
sb.append("定位型別: " + location.getLocationType() + "\n");
sb.append("經 度 : " + location.getLongitude() + "\n");
sb.append("緯 度 : " + location.getLatitude() + "\n");
sb.append("精 度 : " + location.getAccuracy() + "米" + "\n");
sb.append("提供者 : " + location.getProvider() + "\n");
sb.append("速 度 : " + location.getSpeed() + "米/秒" + "\n");
sb.append("角 度 : " + location.getBearing() + "\n");
// 獲取當前提供定位服務的衛星個數
sb.append("星 數 : " + location.getSatellites() + "\n");
sb.append("國 家 : " + location.getCountry() + "\n");
sb.append("省 : " + location.getProvince() + "\n");
sb.append("市 : " + location.getCity() + "\n");
sb.append("城市編碼 : " + location.getCityCode() + "\n");
sb.append("區 : " + location.getDistrict() + "\n");
sb.append("區域 碼 : " + location.getAdCode() + "\n");
sb.append("地 址 : " + location.getAddress() + "\n");
sb.append("興趣點 : " + location.getPoiName() + "\n");
//定位完成的時間
sb.append("定位時間: " + formatUTC(location.getTime(), "yyyy-MM-dd HH:mm:ss") + "\n");
} else {
//定位失敗
sb.append("定位失敗" + "\n");
sb.append("錯誤碼:" + location.getErrorCode() + "\n");
sb.append("錯誤資訊:" + location.getErrorInfo() + "\n");
sb.append("錯誤描述:" + location.getLocationDetail() + "\n");
}
//定位之後的回撥時間
sb.append("回撥時間: " + formatUTC(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + "\n");
return sb.toString();
}
private static SimpleDateFormat sdf = null;
public synchronized static String formatUTC(long l, String strPattern) {
if (TextUtils.isEmpty(strPattern)) {
strPattern = "yyyy-MM-dd HH:mm:ss";
}
if (sdf == null) {
try {
sdf = new SimpleDateFormat(strPattern, Locale.CHINA);
} catch (Throwable e) {
}
} else {
sdf.applyPattern(strPattern);
}
return sdf == null ? "NULL" : sdf.format(l);
}
}
幾個String
<string name="notifyTitle">提示</string>
<string name="notifyMsg">當前應用缺少必要許可權。\n\n請點選\"設定\"-\"許可權\"-開啟所需許可權。</string>
<string name="gpsNotifyMsg">當前應用需要開啟定位功能。\n\n請點選\"設定\"-\"定位服務\"-開啟定位功能。</string>
<string name="setting">設定</string>
<string name="cancel">取消</string>
關於動態許可權
1.檢查限限,如果沒有就申請,申請許可權的方法如下:
ActivityCompat.requestPermissions(this,needRequestPermissonList.toArray(newString[needRequestPermissonList.size()]),PERMISSON_REQUESTCODE);
第一個引數是activity,第二個引數是許可權的陣列,是陣列的格式,,第三個引數是requestCode,requestPermissions()方法內部已經做了判斷
2.回撥方法
onRequestPermissionsResult(int requestCode,String[] permissions, int[] paramArrayOfInt)
通過判斷int[] paramArrayOfInt返回的結果是否 == PackageManager.PERMISSION_GRANTED
如果不等於,則是沒有授權,彈出對話方塊,進行使用者選擇 如果==於,則說明已經授權完成