Created
September 5, 2021 15:18
-
-
Save ayetolusamuel/99281e26a052830b471b89b891204c45 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.chamsmobile.android.features.accountcreation.agent.presentation.ui | |
import android.Manifest | |
import android.annotation.SuppressLint | |
import android.content.BroadcastReceiver | |
import android.content.Context | |
import android.content.Intent | |
import android.content.IntentFilter | |
import android.content.IntentSender | |
import android.content.pm.PackageManager | |
import android.location.Location | |
import android.location.LocationManager | |
import android.os.Bundle | |
import android.os.Looper | |
import android.util.Log | |
import android.view.LayoutInflater | |
import android.view.View | |
import android.view.ViewGroup | |
import android.widget.Toast | |
import androidx.activity.OnBackPressedCallback | |
import androidx.core.app.ActivityCompat | |
import androidx.fragment.app.Fragment | |
import androidx.fragment.app.viewModels | |
import androidx.lifecycle.lifecycleScope | |
import androidx.navigation.fragment.findNavController | |
import androidx.navigation.fragment.navArgs | |
import com.chamsmobile.android.R | |
import com.chamsmobile.android.core.utils.KegowSharedPreferences | |
import com.chamsmobile.android.core.utils.ProgressLoader | |
import com.chamsmobile.android.core.utils.getAgentData | |
import com.chamsmobile.android.core.utils.hide | |
import com.chamsmobile.android.core.utils.isValidEmail | |
import com.chamsmobile.android.core.utils.remove | |
import com.chamsmobile.android.core.utils.show | |
import com.chamsmobile.android.core.utils.tempSaveAgentData | |
import com.chamsmobile.android.core.utils.viewBinding | |
import com.chamsmobile.android.databinding.FragmentAgentAccountBinding | |
import com.chamsmobile.android.features.accountcreation.agent.presentation.viewmodel.AgentViewModel | |
import com.chamsmobile.android.features.accountcreation.agent.presentation.viewstate.CountriesViewState | |
import com.chamsmobile.android.features.accountcreation.agent.presentation.viewstate.StateViewState | |
import com.chamsmobile.android.features.accountcreation.agent.remote.model.body.AgentRemoteBody | |
import com.chamsmobile.android.features.accountcreation.agent.remote.model.response.Country | |
import com.chamsmobile.android.features.accountcreation.agent.remote.model.response.State | |
import com.chamsmobile.android.features.setting.SettingFragmentArgs | |
import com.google.android.gms.common.ConnectionResult | |
import com.google.android.gms.common.GoogleApiAvailability | |
import com.google.android.gms.common.api.ApiException | |
import com.google.android.gms.common.api.ResolvableApiException | |
import com.google.android.gms.location.FusedLocationProviderClient | |
import com.google.android.gms.location.LocationCallback | |
import com.google.android.gms.location.LocationRequest | |
import com.google.android.gms.location.LocationResult | |
import com.google.android.gms.location.LocationServices | |
import com.google.android.gms.location.LocationSettingsRequest | |
import com.google.android.gms.location.LocationSettingsResponse | |
import com.google.android.gms.location.LocationSettingsStatusCodes | |
import com.google.android.gms.tasks.Task | |
import com.google.android.material.snackbar.Snackbar | |
import dagger.hilt.android.AndroidEntryPoint | |
import kotlinx.coroutines.flow.collect | |
import javax.inject.Inject | |
@AndroidEntryPoint | |
class AgentAccountFragment : Fragment(R.layout.fragment_agent_account) { | |
private val binding by viewBinding(FragmentAgentAccountBinding::bind) | |
@Inject | |
lateinit var progressLoader: ProgressLoader | |
private val viewModel: AgentViewModel by viewModels() | |
private val args: SettingFragmentArgs by navArgs() | |
var defCountry: Country? = null | |
var defState: State? = null | |
private var mLocation: Location? = null | |
private lateinit var locationManager: LocationManager | |
private lateinit var locationCallback: LocationCallback | |
/** | |
* Provides the entry point to the Fused Location Provider API. | |
*/ | |
private lateinit var fusedLocationClient: FusedLocationProviderClient | |
override fun onCreate(savedInstanceState: Bundle?) { | |
super.onCreate(savedInstanceState) | |
val agentDataTracker = KegowSharedPreferences(requireContext()).getInt("agent_data_tracker") | |
if (agentDataTracker == 0) { | |
tempSaveAgentData(null, requireContext()) | |
} | |
activity?.onBackPressedDispatcher?.addCallback( | |
this, | |
object : OnBackPressedCallback(true) { | |
override fun handleOnBackPressed() { | |
findNavController().navigateUp() | |
} | |
} | |
) | |
/* register broadcast receivers */ | |
val filter = IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION) | |
filter.addAction(Intent.ACTION_PROVIDER_CHANGED) | |
requireContext().registerReceiver(broadcastReceiver, filter) | |
locationManager = requireContext() | |
.getSystemService(Context.LOCATION_SERVICE) as LocationManager | |
/* Handles the result of location request */ | |
locationCallback = object : LocationCallback() { | |
override fun onLocationResult(locationResult: LocationResult?) { | |
locationResult ?: return | |
for (location in locationResult.locations) { | |
if (locationResult.locations.size > 0) | |
mLocation = location | |
} | |
} | |
} | |
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity()) | |
} | |
override fun onCreateView( | |
inflater: LayoutInflater, | |
container: ViewGroup?, | |
savedInstanceState: Bundle?, | |
): View? { | |
// Inflate the layout for this fragment | |
return inflater.inflate(R.layout.fragment_agent_account, container, false) | |
} | |
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | |
super.onViewCreated(view, savedInstanceState) | |
val agentDataTracker = KegowSharedPreferences(requireContext()).getInt("agent_data_tracker") | |
if (agentDataTracker == 0) { | |
tempSaveAgentData(null, requireContext()) | |
binding.email.setText("") | |
binding.addressStreet.setText("") | |
binding.businessType.setText("") | |
binding.addressLocalGovt.setText("") | |
} | |
setupView() | |
with(binding) { | |
backButton.setOnClickListener { | |
try { | |
findNavController().navigateUp() | |
} catch (exc: Exception) { | |
Log.e(TAG, exc.toString()) | |
} | |
} | |
} | |
binding.next.setOnClickListener { | |
if (checkPermissions()) { | |
if (requestingLocationUpdates()) { | |
saveAgentDetails() | |
} else { | |
getCurrentLocation() | |
} | |
} else { | |
requestPermissions() | |
} | |
} | |
binding.backButton.setOnClickListener { | |
findNavController().navigateUp() | |
} | |
} | |
private fun showStateBottomSheet(states: List<State>) { | |
activity?.supportFragmentManager?.let { | |
StatesSelectionBottomSheetFragment(states).apply { | |
doOnStateSelected { state -> | |
binding.addressState.setText(state.name) | |
binding.addressLocalGovt.show() | |
defState = state | |
} | |
show(it, tag) | |
} | |
} | |
} | |
private fun setupView() { | |
binding.businessName.doAfterTextChanged { | |
if (it.length > 2) { | |
binding.businessType.show() | |
} else { | |
binding.businessType.remove() | |
} | |
} | |
binding.businessType.doAfterTextChanged { | |
if (it.length > 1) { | |
binding.email.show() | |
} else { | |
binding.email.remove() | |
} | |
} | |
binding.email.doAfterTextChanged { | |
if (it.length > 5 && isValidEmail()) { | |
binding.addressCountry.show() | |
} else { | |
binding.addressCountry.remove() | |
} | |
} | |
binding.addressCountry.setOnClickListener { | |
viewModel.getCountries() | |
binding.addressState.remove() | |
} | |
binding.addressState.setOnClickListener { | |
if (defCountry != null) { | |
viewModel.getStates(defCountry?.id.toString()) | |
binding.addressLocalGovt.remove() | |
} | |
} | |
binding.addressLocalGovt.doAfterTextChanged { | |
if (it.length >= 3) { | |
binding.addressHouseNumber.show() | |
} else { | |
binding.addressHouseNumber.hide() | |
} | |
} | |
binding.addressHouseNumber.doAfterTextChanged { | |
if (it.isNotEmpty()) { | |
binding.addressStreet.show() | |
} else { | |
binding.addressStreet.hide() | |
} | |
} | |
binding.addressStreet.doAfterTextChanged { | |
if (it.length >= 3) { | |
binding.busStopLandmark.show() | |
} else { | |
binding.busStopLandmark.hide() | |
} | |
} | |
binding.busStopLandmark.doAfterTextChanged { | |
binding.next.isEnabled = it.length >= 3 | |
} | |
} | |
private fun showCountryBottomSheet(countries: List<Country>) { | |
activity?.supportFragmentManager?.let { | |
CountriesSelectionBottomSheetFragment(countries).apply { | |
doOnCountrySelected { country -> | |
binding.addressCountry.setText(country.name) | |
defCountry = country | |
binding.addressState.show() | |
} | |
show(it, tag) | |
} | |
} | |
} | |
private fun saveAgentDetails() { | |
if (mLocation != null) { | |
val landmark = binding.busStopLandmark.text | |
val email = binding.email.text | |
val houseNumber = binding.addressHouseNumber.text | |
val localGovt = binding.addressLocalGovt.text | |
val stateId = defState?.id | |
val stateName = defState?.name | |
val street = binding.addressStreet.text | |
val lat = mLocation?.latitude | |
val long = mLocation?.longitude | |
val businessName = binding.businessName.text | |
val businessType = binding.businessType.text | |
Log.d("Latitude and Longitude", "Location: $lat + $long") | |
val agentBodyModel = AgentRemoteBody( | |
address_bus_stop_landmark = landmark, | |
address_house_number = houseNumber, | |
address_local_govt = localGovt, | |
address_state_id = stateId!!, | |
address_state_name = stateName!!, | |
address_street = street, | |
address_gps_latitude = lat.toString(), | |
address_gps_longitude = long.toString(), | |
business_name = businessName, | |
business_type = businessType, | |
email = email | |
) | |
val action = | |
AgentAccountFragmentDirections.actionAgentAccountCreationFragmentToAgentSummaryFragment( | |
agent = agentBodyModel, | |
country = defCountry!!.name, args.user | |
) | |
findNavController().navigate(action) | |
tempSaveAgentData(agentRemoteBody = agentBodyModel, context = requireContext()) | |
KegowSharedPreferences(requireContext()).setInt("agent_data_tracker", 1) | |
} else { | |
Toast.makeText(requireContext(), "Unable to detect location..", Toast.LENGTH_SHORT).show() | |
} | |
} | |
private fun isValidEmail(): Boolean { | |
if (!binding.email.text.isValidEmail()) { | |
try { | |
val data = getAgentData(requireContext()) | |
if (data == null) { | |
Toast.makeText(requireContext(), "Invalid email address", Toast.LENGTH_SHORT) | |
.show() | |
return false | |
} | |
} catch (exc: Exception) { | |
Log.e(TAG, "Exception: " + exc.printStackTrace()) | |
} | |
} | |
return true | |
} | |
private fun agentObserver() { | |
lifecycleScope.launchWhenCreated { | |
viewModel.getCountriesFlow.collect { | |
when (it) { | |
is CountriesViewState.Loading -> { | |
val message = it.message?.let { a -> | |
getString(a) | |
} | |
progressLoader.show(message) | |
} | |
is CountriesViewState.Success -> { | |
progressLoader.hide() | |
it.countriesRemoteResponse.let { countries -> | |
if (countries != null) { | |
showCountryBottomSheet(countries.countries) | |
} | |
} | |
} | |
is CountriesViewState.Failure -> { | |
progressLoader.hide() | |
Toast.makeText(context, getString(it.message), Toast.LENGTH_LONG).show() | |
} | |
else -> Unit | |
} | |
} | |
} | |
lifecycleScope.launchWhenCreated { | |
viewModel.getStatesFlow.collect { | |
when (it) { | |
is StateViewState.Loading -> { | |
val message = it.message?.let { a -> | |
getString(a) | |
} | |
progressLoader.show(message) | |
} | |
is StateViewState.Success -> { | |
progressLoader.hide() | |
it.stateRemoteResponse.let { state -> | |
if (state != null) { | |
showStateBottomSheet(state.states) | |
} | |
} | |
} | |
is StateViewState.Failure -> { | |
progressLoader.hide() | |
Toast.makeText(context, getString(it.message), Toast.LENGTH_LONG).show() | |
} | |
else -> Unit | |
} | |
} | |
} | |
} | |
override fun onViewStateRestored(savedInstanceState: Bundle?) { | |
super.onViewStateRestored(savedInstanceState) | |
var data = getAgentData(requireContext()) | |
if (data != null) { | |
setData(data) | |
data = null | |
tempSaveAgentData(data, requireContext()) | |
} else { | |
agentObserver() | |
} | |
} | |
private fun setData(agentRemoteBody: AgentRemoteBody?) { | |
if (agentRemoteBody != null) { | |
binding.addressLocalGovt.show() | |
binding.addressCountry.show() | |
binding.addressState.show() | |
binding.businessName.setText(agentRemoteBody.business_name) | |
binding.businessType.setText(agentRemoteBody.business_type) | |
binding.email.setText(agentRemoteBody.email) | |
binding.busStopLandmark.setText(agentRemoteBody.address_bus_stop_landmark) | |
binding.addressStreet.setText(agentRemoteBody.address_street) | |
binding.addressHouseNumber.setText(agentRemoteBody.address_house_number) | |
binding.addressLocalGovt.setText(agentRemoteBody.address_local_govt) | |
binding.addressState.setText(agentRemoteBody.address_state_name) | |
if (defCountry != null) { | |
binding.addressCountry.setText(defCountry!!.name) | |
} | |
} | |
} | |
override fun onResume() { | |
super.onResume() | |
if (requestingLocationUpdates()) startLocationUpdates() | |
} | |
@SuppressLint("MissingPermission") | |
private fun startLocationUpdates() { | |
val locationRequest: LocationRequest = LocationRequest.create() | |
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY | |
locationRequest.interval = 30 * 1000 | |
locationRequest.fastestInterval = 5 * 1000 | |
fusedLocationClient.requestLocationUpdates( | |
locationRequest, | |
locationCallback, | |
Looper.getMainLooper() | |
) | |
} | |
override fun onPause() { | |
super.onPause() | |
stopLocationUpdates() | |
} | |
private fun stopLocationUpdates() { | |
fusedLocationClient.removeLocationUpdates(locationCallback) | |
} | |
private fun checkPlayServices(): Boolean { | |
val apiAvailability = GoogleApiAvailability.getInstance() | |
val resultCode = apiAvailability.isGooglePlayServicesAvailable(requireContext()) | |
if (resultCode != ConnectionResult.SUCCESS) { | |
if (apiAvailability.isUserResolvableError(resultCode)) { | |
apiAvailability.getErrorDialog( | |
this, | |
resultCode, | |
PLAY_SERVICES_RESOLUTION_REQUEST | |
) | |
} else { | |
requireActivity().finish() | |
} | |
return false | |
} | |
return true | |
} | |
/** | |
* Get the user's current location | |
*/ | |
private fun getCurrentLocation() { | |
val locationRequest: LocationRequest = LocationRequest.create() | |
locationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY | |
locationRequest.interval = 30 * 1000 | |
locationRequest.fastestInterval = 5 * 1000 | |
// Settings client is required to check which settings are enabled, and present the | |
// Location Settings dialog for the user to update their settings with a single tap | |
val builder: LocationSettingsRequest.Builder = LocationSettingsRequest.Builder() | |
.addLocationRequest(locationRequest) | |
builder.setAlwaysShow(true) // this is the key ingredient | |
val result: Task<LocationSettingsResponse> = LocationServices.getSettingsClient( | |
requireContext() | |
).checkLocationSettings(builder.build()) | |
result.addOnCompleteListener { task -> | |
try { | |
val response: LocationSettingsResponse = task.getResult(ApiException::class.java) | |
/** | |
* All location settings are satisfied. The client can initialize location requests here. | |
*/ | |
} catch (exception: ApiException) { | |
when (exception.statusCode) { | |
LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> | |
// Location settings are not satisfied. But could | |
// be fixed by showing the user a dialog. | |
try { | |
// Cast to a resolvable exception. | |
val resolvable = exception as ResolvableApiException | |
// Show the dialog by calling startResolutionForResult(), | |
// and check the result in onActivityResult(). | |
resolvable.startResolutionForResult( | |
requireActivity(), | |
REQUEST_CHECK_SETTINGS | |
) | |
} catch (e: IntentSender.SendIntentException) { | |
// Ignore the error. | |
} catch (e: ClassCastException) { | |
// Ignore, should be an impossible error. | |
} | |
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> { | |
} | |
} | |
} | |
} | |
} | |
// /* set broadcast receiver to detect GPS changes */ | |
private var broadcastReceiver = object : BroadcastReceiver() { | |
override fun onReceive(context: Context, intent: Intent) { | |
/* listen for changes in cell broadcast */ | |
if (LocationManager.PROVIDERS_CHANGED_ACTION == intent.action) { | |
val locationManager = | |
context.getSystemService(Context.LOCATION_SERVICE) as LocationManager | |
val isGpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) | |
// val isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) | |
if (isGpsEnabled) { | |
// Handle Location turned ON | |
Toast.makeText(requireContext(), "LOCATION ENABLED", Toast.LENGTH_LONG).show() | |
} else { | |
Toast.makeText(requireContext(), "LOCATION DISABLED", Toast.LENGTH_LONG).show() | |
// Handle Location turned OFF | |
} | |
} | |
} | |
} | |
/** | |
* Method to check if location is enabled | |
* @return true || false | |
*/ | |
private fun requestingLocationUpdates(): Boolean { | |
val locationManager = requireActivity() | |
.getSystemService(Context.LOCATION_SERVICE) as LocationManager? | |
return locationManager?.isProviderEnabled(LocationManager.GPS_PROVIDER) == true || | |
locationManager?.isProviderEnabled(LocationManager.NETWORK_PROVIDER) == true | |
} | |
@SuppressLint("MissingPermission") | |
private fun getLastLocation() { | |
fusedLocationClient.lastLocation | |
.addOnCompleteListener { taskLocation -> | |
if (taskLocation.isSuccessful && taskLocation.result != null) { | |
val loc = taskLocation.result | |
mLocation = loc | |
} else { | |
Log.w(TAG, "getLastLocation:exception", taskLocation.exception) | |
showSnackbar(R.string.no_location_detected) | |
} | |
} | |
} | |
private fun showSnackbar( | |
snackStrId: Int, | |
actionStrId: Int = 0, | |
listener: View.OnClickListener? = null, | |
) { | |
val snackbar = Snackbar.make( | |
requireActivity().findViewById(android.R.id.content), | |
getString(snackStrId), | |
Snackbar.LENGTH_LONG | |
) | |
if (actionStrId != 0 && listener != null) { | |
snackbar.setAction(getString(actionStrId), listener) | |
} | |
snackbar.show() | |
} | |
private fun requestPermissions() { | |
ActivityCompat.requestPermissions( | |
requireActivity(), | |
arrayOf( | |
Manifest.permission.ACCESS_COARSE_LOCATION, | |
Manifest.permission.ACCESS_FINE_LOCATION | |
), | |
LOCATION_PERMISSION_REQUEST_CODE | |
) | |
} | |
private fun checkPermissions(): Boolean { | |
return ActivityCompat.checkSelfPermission(requireActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission( | |
requireActivity(), | |
Manifest.permission.ACCESS_FINE_LOCATION | |
) == PackageManager.PERMISSION_GRANTED | |
// If we want background location | |
// on Android 10.0 and higher, | |
// use: | |
// ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED | |
} | |
companion object { | |
private const val TAG = "Agent Account Creation" | |
private const val PLAY_SERVICES_RESOLUTION_REQUEST = 9000 | |
private const val REQUEST_CHECK_SETTINGS = 100 | |
private const val LOCATION_PERMISSION_REQUEST_CODE = 5 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment