一 方法介紹
1. 基本權限設置
首先需要在 AndroidManifest.xml 中添加必要權限:
```xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
```
2. 使用 NetworkLocationProvider
```java
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
// 檢查是否啟用了網絡定位
boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if (isNetworkEnabled) {
? ? // 請求位置更新
? ? locationManager.requestLocationUpdates(
? ? ? ? LocationManager.NETWORK_PROVIDER,
? ? ? ? MIN_TIME_BETWEEN_UPDATES, ? ?// 更新間隔,單位毫秒
? ? ? ? MIN_DISTANCE_CHANGE_FOR_UPDATES, ? ?// 最小距離變化,單位米
? ? ? ? new LocationListener() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onLocationChanged(Location location) {
? ? ? ? ? ? ? ? double latitude = location.getLatitude();
? ? ? ? ? ? ? ? double longitude = location.getLongitude();
? ? ? ? ? ? ? ? // 處理獲取到的位置信息
? ? ? ? ? ? }
? ? ? ? ? ??
? ? ? ? ? ? // 其他必要的回調方法實現
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onStatusChanged(String provider, int status, Bundle extras) {}
? ? ? ? ? ??
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onProviderEnabled(String provider) {}
? ? ? ? ? ??
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onProviderDisabled(String provider) {}
? ? ? ? }
? ? );
}
```
3. 主要特點:
- 通過 WiFi 或移動網絡基站信息來確定位置
- 相比 GPS 定位,耗電量更低
- 室內定位效果更好
- 精確度相對較低(誤差可能在幾十米到幾百米)
4. 注意事項:
- Android 6.0 及以上版本需要動態申請權限
- 確保設備已連接網絡
- 考慮網絡定位可能不夠準確的情況
- 建議配合其他定位方式(如 GPS)一起使用
5. 動態權限申請示例:
```java
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
? ? if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)?
? ? ? ? ? ? != PackageManager.PERMISSION_GRANTED) {
? ? ? ? requestPermissions(
? ? ? ? ? ? new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},
? ? ? ? ? ? PERMISSION_REQUEST_CODE
? ? ? ? );
? ? }
}
```
如果需要更高精度的位置信息,建議:
1. 結合 GPS 定位一起使用
2. 使用 Google Play Services 的 FusedLocationProvider
3. 根據實際需求調整更新頻率和精度要求
二 更詳細實現方法
好的,我來提供一個更詳細的實現示例,使用 FusedLocationProvider 實現網絡定位,這是目前 Android 推薦的最佳實踐方案:
1. 首先在 build.gradle 中添加依賴:
```gradle
dependencies {
? ? implementation 'com.google.android.gms:play-services-location:21.0.1'
}
```
2. 完整的示例代碼:
```java
public class LocationActivity extends AppCompatActivity {
? ? private FusedLocationProviderClient fusedLocationClient;
? ? private LocationCallback locationCallback;
? ? private LocationRequest locationRequest;
? ? private static final int PERMISSION_REQUEST_CODE = 1001;
? ??
? ? @Override
? ? protected void onCreate(Bundle savedInstanceState) {
? ? ? ? super.onCreate(savedInstanceState);
? ? ? ? setContentView(R.layout.activity_location);
? ? ? ??
? ? ? ? // 初始化位置客戶端
? ? ? ? fusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
? ? ? ??
? ? ? ? // 創建位置請求
? ? ? ? createLocationRequest();
? ? ? ??
? ? ? ? // 創建位置回調
? ? ? ? createLocationCallback();
? ? ? ??
? ? ? ? // 檢查權限并開始獲取位置
? ? ? ? checkPermissionAndStartLocationUpdates();
? ? }
? ??
? ? private void createLocationRequest() {
? ? ? ? locationRequest = LocationRequest.create()
? ? ? ? ? ? ? ? .setInterval(10000) ? ? ? ? // 期望的更新間隔,單位毫秒
? ? ? ? ? ? ? ? .setFastestInterval(5000) ? // 最快更新間隔
? ? ? ? ? ? ? ? .setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); // 優先使用網絡定位
? ? }
? ??
? ? private void createLocationCallback() {
? ? ? ? locationCallback = new LocationCallback() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void onLocationResult(LocationResult locationResult) {
? ? ? ? ? ? ? ? if (locationResult == null) {
? ? ? ? ? ? ? ? ? ? return;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? for (Location location : locationResult.getLocations()) {
? ? ? ? ? ? ? ? ? ? // 處理位置更新
? ? ? ? ? ? ? ? ? ? updateLocationUI(location);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? };
? ? }
? ??
? ? private void updateLocationUI(Location location) {
? ? ? ? // 示例:更新UI顯示位置信息
? ? ? ? String locationText = String.format(
? ? ? ? ? ? "緯度: %f\n經度: %f\n精確度: %f米",
? ? ? ? ? ? location.getLatitude(),
? ? ? ? ? ? location.getLongitude(),
? ? ? ? ? ? location.getAccuracy()
? ? ? ? );
? ? ? ??
? ? ? ? // 假設有個 TextView 用于顯示位置信息
? ? ? ? TextView locationTextView = findViewById(R.id.location_text);
? ? ? ? locationTextView.setText(locationText);
? ? }
? ??
? ? private void checkPermissionAndStartLocationUpdates() {
? ? ? ? if (ContextCompat.checkSelfPermission(this,?
? ? ? ? ? ? ? ? Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
? ? ? ? ? ? ContextCompat.checkSelfPermission(this,?
? ? ? ? ? ? ? ? Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? startLocationUpdates();
? ? ? ? } else {
? ? ? ? ? ? requestLocationPermissions();
? ? ? ? }
? ? }
? ??
? ? private void requestLocationPermissions() {
? ? ? ? ActivityCompat.requestPermissions(this,
? ? ? ? ? ? new String[]{
? ? ? ? ? ? ? ? Manifest.permission.ACCESS_FINE_LOCATION,
? ? ? ? ? ? ? ? Manifest.permission.ACCESS_COARSE_LOCATION
? ? ? ? ? ? },
? ? ? ? ? ? PERMISSION_REQUEST_CODE
? ? ? ? );
? ? }
? ??
? ? @Override
? ? public void onRequestPermissionsResult(int requestCode,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@NonNull String[] permissions,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@NonNull int[] grantResults) {
? ? ? ? super.onRequestPermissionsResult(requestCode, permissions, grantResults);
? ? ? ? if (requestCode == PERMISSION_REQUEST_CODE) {
? ? ? ? ? ? if (grantResults.length > 0 &&
? ? ? ? ? ? ? ? grantResults[0] == PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? ? ? startLocationUpdates();
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? Toast.makeText(this, "需要位置權限才能獲取位置信息", Toast.LENGTH_SHORT).show();
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ??
? ? private void startLocationUpdates() {
? ? ? ? if (ActivityCompat.checkSelfPermission(this,?
? ? ? ? ? ? ? ? Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
? ? ? ? ? ? ActivityCompat.checkSelfPermission(this,?
? ? ? ? ? ? ? ? Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
? ? ? ? ? ? return;
? ? ? ? }
? ? ? ??
? ? ? ? fusedLocationClient.requestLocationUpdates(locationRequest,
? ? ? ? ? ? ? ? locationCallback,
? ? ? ? ? ? ? ? Looper.getMainLooper());
? ? }
? ??
? ? private void stopLocationUpdates() {
? ? ? ? fusedLocationClient.removeLocationUpdates(locationCallback);
? ? }
? ??
? ? @Override
? ? protected void onResume() {
? ? ? ? super.onResume();
? ? ? ? checkPermissionAndStartLocationUpdates();
? ? }
? ??
? ? @Override
? ? protected void onPause() {
? ? ? ? super.onPause();
? ? ? ? stopLocationUpdates();
? ? }
}
```
3. 在 AndroidManifest.xml 中添加必要的權限:
```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
? ? <!-- 網絡權限 -->
? ? <uses-permission android:name="android.permission.INTERNET" />
? ? <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
? ??
? ? <!-- 位置權限 -->
? ? <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
? ? <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
? ??
? ? <application
? ? ? ? ...
? ? </application>
</manifest>
```
4. 簡單的布局文件 activity_location.xml:
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
? ? android:layout_width="match_parent"
? ? android:layout_height="match_parent"
? ? android:orientation="vertical"
? ? android:padding="16dp">
? ? <TextView
? ? ? ? android:id="@+id/location_text"
? ? ? ? android:layout_width="wrap_content"
? ? ? ? android:layout_height="wrap_content"
? ? ? ? android:textSize="16sp" />
</LinearLayout>
```
主要特點和說明:
1. 使用 FusedLocationProvider:
- 自動選擇最佳的位置提供者(網絡或GPS)
- 更省電和高效
- 提供更好的定位精確度
2. LocationRequest 配置:
- `setInterval()`: 設置期望的更新間隔
- `setFastestInterval()`: 設置最快更新間隔
- `setPriority()`: 設置優先級
? - PRIORITY_BALANCED_POWER_ACCURACY: 城市級別精確度(100米左右),主要使用網絡定位
? - PRIORITY_HIGH_ACCURACY: 最高精確度,會使用GPS
? - PRIORITY_LOW_POWER: 城市級別精確度(10公里左右)
? - PRIORITY_PASSIVE: 被動接收位置更新
3. 生命周期管理:
- 在 onResume() 中開始位置更新
- 在 onPause() 中停止位置更新,避免后臺消耗電量
4. 權限處理:
- 運行時權限請求
- 權限檢查
- 權限結果處理
使用建議:
1. 根據實際需求調整更新頻率:
- 導航應用可能需要更頻繁的更新
- 天氣應用可以使用較長的更新間隔
2. 注意電池消耗:
- 合理設置更新間隔
- 不需要時及時停止位置更新
3. 錯誤處理:
- 添加網絡檢查
- 處理位置服務未開啟的情況
- 添加超時處理
?