마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

위치 활성화 후 메세지

0 추천

앱에서 위치 서비스를 켜는 기능을 만들고 있습니다. 

 

구글 위치서비스 활성화를 이용하고 있습니다.

implementation 'com.google.android.gms:play-services-location:20.0.0'
if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(5000);
    locationRequest.setFastestInterval(1000);

    LocationSettingsRequest.Builder locationSettingsRequestBuilder
                                 = new LocationSettingsRequest.Builder();

    locationSettingsRequestBuilder.addLocationRequest(locationRequest);
    locationSettingsRequestBuilder.setAlwaysShow(true);

    SettingsClient settingsClient = LocationServices.getSettingsClient(getActivity());


    Task<LocationSettingsResponse> task
         = settingsClient.checkLocationSettings(locationSettingsRequestBuilder.build());
    task.addOnSuccessListener(getActivity(), new OnSuccessListener<LocationSettingsResponse>() {
        @Override
        public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
            }
    });
    task.addOnFailureListener(getActivity(), new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            if (e instanceof ResolvableApiException){
                try {
                    ResolvableApiException resolvableApiException = (ResolvableApiException) e;
                    resolvableApiException.startResolutionForResult(getActivity(),REQUEST_CHECK_SETTINGS);
                } catch (IntentSender.SendIntentException ex) {
                    ex.printStackTrace();
                }
           }
       }
   });

코드는 대충 이렇구요. 위에 코드 실행후, 위치 켜져있는지 감지해서 toast 메세지 같은걸로 띄우고 싶습니다. 위치 감지하는 건 찾아보니,

if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
    Toast.makeText(getActivity(),"GPS is ON",Toast.LENGTH_SHORT).show();
}else {
    Toast.makeText(getActivity(),"GPS is OFF",Toast.LENGTH_SHORT).show();
}

대충 이런 식으로 띄울 수 있던데, 버튼 클릭리스너 코드 안에 같이 넣으면, 버튼 클릭시에 메세지가 동시에 나타납니다.

위치를 활성화/비활성화 한 이후에 메세지를 나타내고 싶은데 어떻게 해야 될까요?

걍 취미로 (230 포인트) 님이 2022년 9월 20일 질문
걍 취미로님이 2022년 9월 20일 수정

2개의 답변

0 추천
먼저 location 권한 처리에 관한 개발자 가이드를 읽어 보세요.

https://developer.android.com/training/location/permissions

안드로이드에서 권한 처리가 어떻게 흘러가는지 이해하셔야 해당 처리가 가능할 것으로 보입니다.
spark (224,800 포인트) 님이 2022년 9월 20일 답변
제가 질문을 잘 이해한건지 모르겠는데, 님이 말하는 위치 활성화/비활성화가 권한관련이 맞는 것도 같고 아닌 것도 같네요. isProviderEnabled는 권한과는 다른 내용이라. isProviderEnabled에 대한 처리를 하려면
API 문서에 나온대로 BroadCastReceiver를 통해 처리하셔야 할 것으로 보이는데요.

Returns the current enabled/disabled status of the given provider. To listen for changes, see PROVIDERS_CHANGED_ACTION. Before API version Build.VERSION_CODES.LOLLIPOP, this method would throw SecurityException if the location permissions were not sufficient to use the specified provider.

그리고 어쨌건간에 권한처리는 반드시 해야할 사항으로 보여요.
0 추천

location service의 활성화 여부를 체크해서 처리하는 코드는 다음과 같이 처리하시면 될 것 같습니다.

먼저, 아래처럼 메소드를 재활용하기 위해서 Location provider의 활성화 여부를 체크하는 유틸리티 클래스를 하나 만드세요.

public class LocationUtils {

    private final LocationManager locationManager;

    public LocationUtils(Context context) {
        locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    }

    public boolean isLocationServiceEnabled() {
        return isGpsProviderEnabled() && isNetworkProviderEnabled();
    }

    public boolean isGpsProviderEnabled() {
        return isLocationProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    public boolean isNetworkProviderEnabled() {
        return isLocationProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

    private boolean isLocationProviderEnabled(String provider) {
        try {
            return locationManager.isProviderEnabled(provider);
        } catch(Exception ex) {
            return false;
        }
    }
}

 

그리고 사용자를 location서비스 세팅화면으로 보낼 ActivityResultContract를 만듧니다. ActivityResultContract는 최근에 도입된 것으로 startActivityForResult를 대체하기 위해  사용되고 있습니다.

public class LocationSettingsContracts extends ActivityResultContract<Void, Void> {

    @NonNull
    @Override
    public Intent createIntent(@NonNull Context context, Void s) {
        return new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    }

    @Override
    public Void parseResult(int i, @Nullable Intent intent) {
        // LocationUtils를 사용해서 세팅값을 체크할 것이므로 Void타입을 리턴.
        return null;
    }
}

 

액티비티에서는, 해당 기능이 활성화 되어 있지 않으면, 설정화면으로 사용자를 보냅니다.

private LocationUtils locationUtils;

private ActivityResultLauncher<Void> locationSettingsContract = registerForActivityResult(
            new LocationSettingsContracts(),
            unused -> handleLocationSettings()
    );

private void handleLocationSettings() {
        if (!locationUtils.isGpsProviderEnabled()){
            Toast.makeText(this, "GPS is OFF",Toast.LENGTH_SHORT).show(); 
            return;
        }
        
        fetchLocation();
    }

   @Override
    protected void onCreate(Bundle savedInstanceState) {
        locationUtils = new LocationUtils(this);
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initViews();
    }

    private void initViews() {
        Button actionButton = findViewById(R.id.actionButton);
        actionButton.setOnClickListener(v -> {
            requestLocation();
        });
    }

    private void requestLocation() {
        if (!locationUtils.isGpsProviderEnabled()){
            locationSettingsContract.launch(null);
            return;
        }

       fetchLocation();
    }

 private void fetchLocation() {

}

 

 위에서 나온 흐름대로 해당 서비스가 비활성화 되어 있다면, 사용자를 설정화면으로 보내고, 설정 결과를 받아온 후에 위치를 요청하고, 서비스가 활성화 상태라면 바로 위치를 요청하면 되겠죠.

종이에 위의 흐름을 흐름도나 Pseudo code 형태로 정리해보시면 그렇게 어렵지 않게 이해하실 수 있을 겁니다.

spark (224,800 포인트) 님이 2022년 9월 21일 답변
...