2017-05-23 9 views
2

안녕하세요 사용자 위치를 얻을 수있는 Android지도 애플리케이션을 만드는 중입니다. 사용자가지도를 열 때 위치가 정확하지 않고 천천히 위치를 찾아냅니다.getAccuracy()가 100보다 작을 때 처리기를 중지하는 방법

나는 이것을 시도했다. 그러나 그것은 여전히 ​​핸들러를 호출하고 TOASTS는 멈추지 않을 것입니다.

private LocationManager locationManager; 

private Handler handler = new Handler(); 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_maps_page); 

locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); 

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() { 
     @Override 
     public void onLocationChanged(Location location) { 

     } 

     @Override 
     public void onStatusChanged(String provider, int status, Bundle extras) { 

     } 

     @Override 
     public void onProviderEnabled(String provider) { 
       handler.postDelayed(runnable,3000); 
     } 

     @Override 
     public void onProviderDisabled(String provider) { 

      handler.removeCallbacks(runnable); 
     } 
    }); 

     private Runnable runnable = new Runnable() { 
    @Override 
    public void run() { 

     getCurrentLocation(); 

     Toast.makeText(mapsPage.this, "GETTING LOCATION", Toast.LENGTH_SHORT).show(); 

     handler.postDelayed(this, 3000); 
    } 
}; 

    private void getCurrentLocation() { 
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     return; 
    } 
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); 
    if (location != null) { 
     longitude = location.getLongitude(); 
     latitude = location.getLatitude(); 

     moveMap(); 

     Integer loc = Math.round(location.getAccuracy()); 
     textings.setText(Integer.toString(loc)); 

     if(loc <= 100) 
    { 
     handler.removeCallbacks(runnable); 

     Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show(); 
    } 

    } 
} 

//Function to move the map 
private void moveMap() { 

    LatLng latLng = new LatLng(latitude, longitude); 

    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng)); 
    mMap.animateCamera(CameraUpdateFactory.zoomTo(17)); 
    mMap.addMarker(new MarkerOptions().position(latLng).draggable(false)); 

} 
나는 사용자의 위치를 ​​확인 5 초마다 실행 핸들러를 추가 한

하고 getAccuracy 데이터가 같거나 낮은 중 하나 인 경우 100보다가 중지됩니다. 어떻게하면 좋을까요?

답변

3

getCurrentLocation은 handler.removeCallbacks(runnable);을 호출 할 수 있지만 그 다음 실행 파일은 항상 handler.postDelayed(this, 3000);을 바로 호출합니다.

이 문제를 해결하려면 Runnable이 다시 게시해야하는지 확인하기위한 조건이 있어야합니다.

@Override 
public void run() { 
    if(!getCurrentLocation()) { 
     handler.postDelayed(this, 3000); 
    } 
} 

: 다른 실행을해야하는 경우

private boolean getCurrentLocation() { 
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && 
      ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { 
     return false; 
    } 
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); 
    if (location != null) { 
     longitude = location.getLongitude(); 
     latitude = location.getLatitude(); 

     moveMap(); 

     Integer loc = Math.round(location.getAccuracy()); 
     textings.setText(Integer.toString(loc)); 

     if(loc <= 100) { 
      handler.removeCallbacks(runnable); 
      Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show(); 
      return true; 
     } 
    } 
    return false; 
} 

를 그런 다음 Runnable를 점검 :

해결책은 getCurrentLocation이 성공하면 부울이 (충분히)을 나타내는 반환하게하는 것

그러나은 모두 위치 알림기의 onLocationChanged에서 위치를 확인하고 그 위치가 충분히 정확하다면. 그럼 당신은 Runnable을 전혀 필요로하지 않습니다.

+0

안녕하세요, 저는 이걸 가지고 모든 단호한 사람을 끌어 냈습니다. 그리고 저는 제 대답을 찾았습니다. 나는 timerTask를 사용했고 snackbars로 토스트를 교체했으며 정말 잘 돌아갔다. 난 당신의 코드를 시도하고 그것을 작동하고, 당신은 upvote 자격과 대답을받을 자격이. 도움말 및 설명에 다시 한 번 감사드립니다! : D –

+0

하지만 사용자 위치를 효율적으로 찾아내는 코드 또는 접근 방식을 사용하고 있습니까 아니면 다른 방법을 고려해야합니까? –

2

RobCo의 답변은 정확한 질문으로 받아 들여야합니다. 질문에 직접 답하고 추가 핵심 통찰력을 제공하기 때문에 (즉, 실제로 Runnable이 필요하지 않음)

그러나 RobCo의 접근 방식이 궁금해서 그 중 하나를 구현했습니다.

우리가 Runnable을 피하고 대신 Google 콜백에 의존한다면 더 새로운 위치 제공자 API (LocatonServices.FusedLocationApi) 만 사용하여 도망 갈 수 있다는 사실이 밝혀졌습니다. 이전 LocationManager API는 제거 될 수 있습니다.

public class MainActivity extends AppCompatActivity implements 
     ActivityCompat.OnRequestPermissionsResultCallback, GoogleApiClient.OnConnectionFailedListener, 
     GoogleApiClient.ConnectionCallbacks, 
     com.google.android.gms.location.LocationListener { 

    private static final String TAG = MainActivity.class.getSimpleName(); 

    private static final int PERMISSION_REQUEST_CODE = 10001; 
    public static final int LOCATION_UPDATE_INTERVAL = 5000; // milliseconds 
    private GoogleApiClient googleApiClient; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     googleApiClient = new GoogleApiClient.Builder(this, this, this) 
       .enableAutoManage(this, this) 
       .addApi(LocationServices.API) 
       .build(); 

     googleApiClient.connect(); 
    } 

    private void requestPermission() { 
     ActivityCompat.requestPermissions(this, 
       new String[]{ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE); 
    } 

    private void initLocationServices() { 
     try { 
      // make initial, synchronous request for current location 
      Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient); 
      if (location != null) { 
       moveMap(location); 
      } 

      // request future location updates which will come in as callbacks later, when available 
      LocationRequest locationRequest = new LocationRequest(); 
      locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
      locationRequest.setInterval(LOCATION_UPDATE_INTERVAL); 
      LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this); 
     } catch (SecurityException se) { 
      Log.w(TAG, "App does not have sufficient permission to request location. " + 
        "Requesting permission now..."); 
      requestPermission(); 
     } 
    } 

    private void moveMap(Location location) { 
     Log.v(TAG, "moveMap"); 

     // TODO: actual map moving code goes here 
    } 

    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { 
     Log.e(TAG, "Connection failed:" + connectionResult.getErrorMessage()); 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
     super.onRequestPermissionsResult(requestCode, permissions, grantResults); 
     if (requestCode == PERMISSION_REQUEST_CODE && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) { 
      Log.v(TAG, "User granted permission. Will request current location."); 
      initLocationServices(); 
     } else { 
      Log.w(TAG, "User did not grant permission. Cannot request location. Cannot proceed."); 
     } 
    } 

    @Override 
    public void onLocationChanged(Location newLocation) { 
     Log.v(TAG, "onLocationChanged:" + newLocation.toString()); 
     moveMap(newLocation); 
    } 

    @Override 
    public void onConnected(@Nullable Bundle bundle) { 
     if ((ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED) 
       && (ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED)) { 
      initLocationServices(); 
     } else { 
      Log.w(TAG, "onCreate: requesting sufficient permission from user"); 
      requestPermission(); 
     } 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Log.v(TAG, "onConnectionSuspended"); 
    } 
} 

이 특정 구현의 단점은 다음과 같습니다 (대신 클라이언트에서 정기적 인 설문 조사를 사용) 위치 변경시/경우

그래서,이 구현에서, 나는 Google 위치 서비스 트리거 콜백을하자 MainActivity가 여러 개의 인터페이스를 구현하고 약간의 혼란을 일으킨다는 것 (이 모든 메소드는 여기서 무엇을하고 있습니까?)

Dunno. 어쩌면 유용 할 것입니다. 어쨌든 앱에 행운을 비네.

+0

이봐, 각하, 나는 모든 해결책을 찾았고 나의 해결책을 찾았으며 지금은 타이머 작업을 사용하고있다. 정말 잘 작동한다.그러나 도움과 설명을 주신 선생님께서는 자격이 있고 upvote를 받으셔야합니다. 도와 줘서 고마워! –

+0

하지만 사용자 위치를 효율적으로 찾아내는 코드 또는 접근 방식이 궁금하거나 선생님의 접근 방법이 더 효율적입니까? –

+1

좋아하는 해결책을 찾은 것을 축하드립니다. 그리고 유권자 여러분 께 감사드립니다. 어떤 접근 방식이 가장 효율적인 지 잘 모르겠습니다. 내 테스트 앱에서 Google의 LocationServices.FusedLocationApi는 태블릿이 책상 위에 앉아 있어도 2 ~ 5 초마다 내 앱을 업데이트합니다. 그래서, 꽤 많은 콜백을 생성합니다. 5 초마다 위치를 묻는 TimerTask와 비슷합니다. 또한 FWIW, 폴링 방식을 구현하는 경우 사용자가 앱을 배경으로두고 다시 시작하면 문제와 메모리 누수가 발생합니다. –