نمایش موقعیت کاربر – B4A

Android SDK Resources

نسخه 1.1

هدف از این بخش از پروژه، نمایش یک نشانگر بر روی موقعیت فعلی کاربر و به‌روزرسانی مکان نمایشگر با تغییر موقعیت جغرافیایی کاربر است.

جهت پیاده سازی این مثال، باید کتابخانه های زیر را در پنجره Libraries Manager تیک بزنید:

  • FusedLocationProvider
  • RuntimePermissions
  • GPS
  • Reflection
  • JavaObject

سپس در فایل Main پروژه در قسمت Region Project Attributes خطوط زیر را اضافه کنید:

#AdditionalJar: common-release.aar
#AdditionalJar: com.google.android.gms:play-services-location

جهت استفاده از کتابخانه FusedLocationProvider باید از کتابخانه Google play services نسخه 27 به بالا و کتابخانه play-services-location استفاده نمایید.

جهت نصب این 2 کتابخانه ابتدا به پوشه نصب نرم افزار b4a رفته و فایل B4ASdkManager.jar را باز کنید. سپس در قسمت جستجوی sdk manager کتابخانه google play services را جستجو کنید، در صورتی که این کتابخانه نصب نشده است، تیک آن را بزنید. سپس کتابخانه play-services-location را جستجو کنید و مطمئن شوید که آخرین نسخه موارد زیر نصب شده است:

  • com.google.android.gms:play-services-location-licence (Google Maven)
  • com.google.android.gms:play-services-location (Google Maven)

همچنین به منوی project رفته و روی گزینه Manifest editor کلیک کنید و در پنجره باز شده محتوای زیر را به manifest اضافه کنید:

            AddApplicationText(<meta-data
   android:name="com.google.android.gms.version"
   android:value="@integer/google_play_services_version" />)
        

جهت کسب اطلاعات بیشتر در مورد کتابخانه FusedLocationProvider به این صفحه مراجعه نمایید.

activity_user_location.bal

در Visual designer زیر که مربوط به Layout اکتیویتی نمایش موقعیت کاربر است، یک View ی نقشه و یک دکمه وجود دارد که پس از کلیک روی آن فرایند دریافت موقعیت کاربر اجرا میشود.

جهت تعریف شیء نقشه در کد روی View ی مربوط به نقشه که نام آن در این مثال NeshanMapSdk1 است راست کلیک کرده و از منوی باز شونده Generate، گزینه Dim NeshanMapSdk1 as NeshanMapSdk را انتخاب میکنیم. پس از این عمل، شیء نقشه در فایل کد مربوط به اکتیویتی نمای موقعیت کاربر (UserLocationActivity) در قسمت Globals اضافه میشود.

            Sub Globals
	'These global variables will be redeclared each time the activity is created.
	'These variables can only be accessed from this module.

	Private NeshanMapSdk1 As NeshanMapSdk
End Sub
        

جهت پیاده سازی متد کلیک روی دکمه، Visual designer مربوط به AddMarkerActivity را باز کرده، روی دکمه ای که قبلا اضافه شده است راست کلیک کنید و از زیر منوی Generate گزینه Click را انتخاب کنید تا Event کلیک مربوط به دکمه در AddMarkerActivity پیاده سازی شود. سپس تکه کد مربوط به اضافه کردن نشانگر را درون بدنه آن اضافه کنید.

            Private Sub FindMyLocationButton_Click

End Sub
        

دریافت موقعیت کاربر

جهت دریافت موقعیت کاربر، نیاز به یک شیء از نوع FusedLocationProvider و یک شیء از نوع RuntimePermissions دارید. 2 متغیر فوق را در قسمت Globals به صورت زیر تعریف کنید:

            Private fusedLocationProvider1 As FusedLocationProvider
Private rp As RuntimePermissions
Private package As String
Private reflector As Reflector
Private userMarker As JavaObject
Private isGpsEnabled As Boolean = False
        

فرآیند دریافت لوکیشن کاربر به این صورت است که کتابخانه FusedLocationProvider ابتدا سعی میکند آخرین لوکیشنی که بدست آورده را نمایش دهد. 

  • در صورتی که لوکیشن وجود داشت، یک مارکر در لوکیشن اضافه میکند و دوربین روی آن نقطه قرار میگیرد. 
  • در صورتی که لوکیشن وجود نداشت، ابتدا چک میکند که Gps روشن است یا خیر
    • اگر gps روشن بود، چک میکند که آیا دسترسی لوکیشن دریافت شده است یا نه
      • اگر دسترسی لوکیشن دریافت شده بود، توسط شیء fusedLocationProvider درخواست لوکیشن را ارسال میکند و وقتی لوکیشن دریافت شد، متد locationChanged صدا زده میشود و مارکر یوزر به نقشه اضافه میشود و دوربین روی نقطه یوزر قرار میگیرد.
      • اگر دسترسی لوکیشن دریافت نشده بود، Permission not granted لاگ میشود.
    • اگر gps روشن نبود، صفحه تنظیمات مربوط به gps را باز میکند تا یوزر gps را روشن کند.

نمایش محدوده تقریبی کاربر

زمانی که از موقعیت تقریبی کاربر (ACCESS_COARSE_LOCATION) برای نمایش موقعیت کاربر استفاده میکنید، همانطور که از نامش پیداست، موقعیتی که روی نقشه نمایش داده میشود تقریبی است. برای نمایش محدوده تقریبی کاربر میتوانید از متد زیر استفاده نمایید:

            NeshanMapSdk1.showAccuracyCircle(userLocation)
        

پارامتر ورودی این متد از نوع Location است که طبق توضیحات بالا باید متغیر userLocation به آن پاس داده شود. طبق مثال بالا این متد باید در متد FusedLocationProvider1_LocationChanged صدا زده شود.

مثال

در مثال پایین، پس از کلیک روی دکمه FindMyLocation، متد Initialize با نام شیء fusedLocationProvider1 روی شیء fusedLocationProvider1 صدا زده میشود. سپس متد Connect روی شیء fusedLocationProvider صدا زده میشود. در صورتی که اتصال به درستی بر قرار شود، تابع مربوط به FusedLocationProvider به نام connectionSuccess صدا زده میشود.

نکته: در مثال پایین متد connectionSuccess به صورت FusedLocationProvider1_ConnectionSuccess نوشته شده است، عبارت FusedLocationProvider1 همان عبارتی است که هنگام Initialize کردن شیء FusedLocationProvider به عنوان پارامتر به متد Initialize ارسال شده است.

            Private Sub FindMyLocationButton_Click
	fusedLocationProvider1.Initialize("fusedLocationProvider1")
	fusedLocationProvider1.Connect
End Sub

Sub FusedLocationProvider1_ConnectionSuccess
	Private lastKnownLocation As Location = fusedLocationProvider1.GetLastKnownLocation
	If lastKnownLocation.IsInitialized Then
		Private userMarkerDrawable As Int
		package = reflector.GetStaticField("anywheresoftware.b4a.BA", "packageName")
		userMarkerDrawable = reflector.GetStaticField(package & ".R$drawable", "ic_user_marker")
		userMarker = NeshanMapSdk1.addMarker(userMarkerDrawable,25,lastKnownLocation.Latitude,lastKnownLocation.Longitude)
		NeshanMapSdk1.moveCamera(lastKnownLocation.Latitude,lastKnownLocation.Longitude,0.5)
	Else
		getLocationSettings
	End If
End Sub

Sub getLocationSettings
	Private locationSettingsRequestBuilder As LocationSettingsRequestBuilder
	locationSettingsRequestBuilder.Initialize
	fusedLocationProvider1.CheckLocationSettings(locationSettingsRequestBuilder.Build)
End Sub

Sub FusedLocationProvider1_ConnectionFailed(connectionResult As Int)
	Log("Connection failed. Result code: " & connectionResult)
End Sub

Sub FusedLocationProvider1_LocationSettingsChecked(locationSettingsResult As LocationSettingsResult)
	isGpsEnabled = locationSettingsResult.GetLocationSettingsStates.IsGpsUsable
	GetLocationPermission
End Sub

Sub FusedLocationProvider1_LocationChanged(location As Location)
	Private userMarkerDrawable As Int
	package = reflector.GetStaticField("anywheresoftware.b4a.BA", "packageName")
	userMarkerDrawable = reflector.GetStaticField(package & ".R$drawable", "ic_user_marker")
	userMarker = NeshanMapSdk1.addMarker(userMarkerDrawable,25,location.Latitude,location.Longitude)
	NeshanMapSdk1.showAccuracyCircle(userLocation)
	NeshanMapSdk1.moveCamera(location.Latitude,location.Longitude,0.5)
End Sub

Sub GetLocationPermission
	runtimePermissions.CheckAndRequest(runtimePermissions.PERMISSION_ACCESS_FINE_LOCATION)
	Wait for Activity_PermissionResult (Permission As String, Result As Boolean)
	If Result Then
		If isGpsEnabled Then
			'Get user location
			Private LocationRequest1 As LocationRequest
			LocationRequest1.Initialize
			LocationRequest1.SetPriority(LocationRequest1.Priority.PRIORITY_HIGH_ACCURACY)
			fusedLocationProvider1.RequestLocationUpdates(LocationRequest1)
		Else
			NeshanMapSdk1.openGpsSettings
		End If
	Else
		Log("Permission not granted")
	End If
End Sub
        

تابع getLocationSettings توسط شیء fusedLocationProvider یک درخواست برای چک کردن روشن بودن Gps ارسال میکند، پاسخ درخواست در تابعی به نام LocationSettingsChecked ارسال خواهد شد. توسط متغیر locationSettingsResult میتوان وضعیت gps را دریافت کرد.

تابع getLocationPermission جهت گرفتن دسترسی gps است. در صورتی که دسترسی gps از سمت کاربر ارسال شود، تابع RequestLocationUpdates روی شیء fusedLocationProvider صدا زده خواهد شد و شروع به دریافت موقعیت کاربر میکند، در صورتی که موقعیت کاربر دریافت شد، تابع LocationChanged صدا زده میشود و موقعیت کاربر را در متغیر location تحویل میدهد. و در پایان یک مارکر روی نقطه کاربر اضافه میشود.

نکته: در صورتی که ورژن اندروید دستگاه کاربر پایین تر از اندروید 6 باشد حاصل تابع GetLocationPermission همیشه True خواهد بود و فرایند دریافت موقعیت کاربر بدون دریافت دسترسی انجام خواهد شد چرا که دریافت دسترسی از کاربر از اندروید ورژن 6 به بعد در سیستم عامل اندروید پیاده سازی شده است.

نسخه 1.0

هدف از این بخش از پروژه، نمایش یک نشانگر بر روی موقعیت فعلی کاربر و به‌روزرسانی مکان نمایشگر با تغییر موقعیت جغرافیایی کاربر است.

جهت پیاده سازی این مثال، باید کتابخانه های زیر را در پنجره Libraries Manager تیک بزنید:

  • FusedLocationProvider
  • RuntimePermissions
  • GPS
  • Reflection
  • JavaObject

سپس در فایل Main پروژه در قسمت Region Project Attributes خطوط زیر را اضافه کنید:

#AdditionalJar: common-release.aar
#AdditionalJar: com.google.android.gms:play-services-location

جهت استفاده از کتابخانه FusedLocationProvider باید از کتابخانه Google play services نسخه 27 به بالا و کتابخانه play-services-location استفاده نمایید.

جهت نصب این 2 کتابخانه ابتدا به پوشه نصب نرم افزار b4a رفته و فایل B4ASdkManager.jar را باز کنید. سپس در قسمت جستجوی sdk manager کتابخانه google play services را جستجو کنید، در صورتی که این کتابخانه نصب نشده است، تیک آن را بزنید. سپس کتابخانه play-services-location را جستجو کنید و مطمئن شوید که آخرین نسخه موارد زیر نصب شده است:

  • com.google.android.gms:play-services-location-licence (Google Maven)
  • com.google.android.gms:play-services-location (Google Maven)

همچنین به منوی project رفته و روی گزینه Manifest editor کلیک کنید و در پنجره باز شده محتوای زیر را به manifest اضافه کنید:

            AddApplicationText(<meta-data
   android:name="com.google.android.gms.version"
   android:value="@integer/google_play_services_version" />)
        

جهت کسب اطلاعات بیشتر در مورد کتابخانه FusedLocationProvider به این صفحه مراجعه نمایید.

activity_user_location.bal

در Visual designer زیر که مربوط به Layout اکتیویتی نمایش موقعیت کاربر است، یک View ی نقشه و یک دکمه وجود دارد که پس از کلیک روی آن فرایند دریافت موقعیت کاربر اجرا میشود.

جهت تعریف شیء نقشه در کد روی View ی مربوط به نقشه که نام آن در این مثال NeshanMapSdk1 است راست کلیک کرده و از منوی باز شونده Generate، گزینه Dim NeshanMapSdk1 as NeshanMapSdk را انتخاب میکنیم. پس از این عمل، شیء نقشه در فایل کد مربوط به اکتیویتی نمای موقعیت کاربر (UserLocationActivity) در قسمت Globals اضافه میشود.

            Sub Globals
	'These global variables will be redeclared each time the activity is created.
	'These variables can only be accessed from this module.

	Private NeshanMapSdk1 As NeshanMapSdk
End Sub
        

جهت پیاده سازی متد کلیک روی دکمه، Visual designer مربوط به AddMarkerActivity را باز کرده، روی دکمه ای که قبلا اضافه شده است راست کلیک کنید و از زیر منوی Generate گزینه Click را انتخاب کنید تا Event کلیک مربوط به دکمه در AddMarkerActivity پیاده سازی شود. سپس تکه کد مربوط به اضافه کردن نشانگر را درون بدنه آن اضافه کنید.

            Private Sub FindMyLocationButton_Click

End Sub
        

دریافت موقعیت کاربر

جهت دریافت موقعیت کاربر، نیاز به یک شیء از نوع FusedLocationProvider و یک شیء از نوع RuntimePermissions دارید. 2 متغیر فوق را در قسمت Globals به صورت زیر تعریف کنید:

            Private fusedLocationProvider1 As FusedLocationProvider
Private rp As RuntimePermissions
Private package As String
Private reflector As Reflector
Private userMarker As JavaObject
Private isGpsEnabled As Boolean = False
        

فرآیند دریافت لوکیشن کاربر به این صورت است که کتابخانه FusedLocationProvider ابتدا سعی میکند آخرین لوکیشنی که بدست آورده را نمایش دهد. 

  • در صورتی که لوکیشن وجود داشت، یک مارکر در لوکیشن اضافه میکند و دوربین روی آن نقطه قرار میگیرد. 
  • در صورتی که لوکیشن وجود نداشت، ابتدا چک میکند که Gps روشن است یا خیر
    • اگر gps روشن بود، چک میکند که آیا دسترسی لوکیشن دریافت شده است یا نه
      • اگر دسترسی لوکیشن دریافت شده بود، توسط شیء fusedLocationProvider درخواست لوکیشن را ارسال میکند و وقتی لوکیشن دریافت شد، متد locationChanged صدا زده میشود و مارکر یوزر به نقشه اضافه میشود و دوربین روی نقطه یوزر قرار میگیرد.
      • اگر دسترسی لوکیشن دریافت نشده بود، Permission not granted لاگ میشود.
    • اگر gps روشن نبود، صفحه تنظیمات مربوط به gps را باز میکند تا یوزر gps را روشن کند.

مثال

در مثال پایین، پس از کلیک روی دکمه FindMyLocation، متد Initialize با نام شیء fusedLocationProvider1 روی شیء fusedLocationProvider1 صدا زده میشود. سپس متد Connect روی شیء fusedLocationProvider صدا زده میشود. در صورتی که اتصال به درستی بر قرار شود، تابع مربوط به FusedLocationProvider به نام connectionSuccess صدا زده میشود.

نکته: در مثال پایین متد connectionSuccess به صورت FusedLocationProvider1_ConnectionSuccess نوشته شده است، عبارت FusedLocationProvider1 همان عبارتی است که هنگام Initialize کردن شیء FusedLocationProvider به عنوان پارامتر به متد Initialize ارسال شده است.

            Private Sub FindMyLocationButton_Click
	fusedLocationProvider1.Initialize("fusedLocationProvider1")
	fusedLocationProvider1.Connect
End Sub

Sub FusedLocationProvider1_ConnectionSuccess
	Private lastKnownLocation As Location = fusedLocationProvider1.GetLastKnownLocation
	If lastKnownLocation.IsInitialized Then
		Private userMarkerDrawable As Int
		package = reflector.GetStaticField("anywheresoftware.b4a.BA", "packageName")
		userMarkerDrawable = reflector.GetStaticField(package & ".R$drawable", "ic_user_marker")
		userMarker = NeshanMapSdk1.addMarker(userMarkerDrawable,25,lastKnownLocation.Latitude,lastKnownLocation.Longitude)
		NeshanMapSdk1.moveCamera(lastKnownLocation.Latitude,lastKnownLocation.Longitude,0.5)
	Else
		getLocationSettings
	End If
End Sub

Sub getLocationSettings
	Private locationSettingsRequestBuilder As LocationSettingsRequestBuilder
	locationSettingsRequestBuilder.Initialize
	fusedLocationProvider1.CheckLocationSettings(locationSettingsRequestBuilder.Build)
End Sub

Sub FusedLocationProvider1_ConnectionFailed(connectionResult As Int)
	Log("Connection failed. Result code: " & connectionResult)
End Sub

Sub FusedLocationProvider1_LocationSettingsChecked(locationSettingsResult As LocationSettingsResult)
	isGpsEnabled = locationSettingsResult.GetLocationSettingsStates.IsGpsUsable
	GetLocationPermission
End Sub

Sub FusedLocationProvider1_LocationChanged(location As Location)
	Private userMarkerDrawable As Int
	package = reflector.GetStaticField("anywheresoftware.b4a.BA", "packageName")
	userMarkerDrawable = reflector.GetStaticField(package & ".R$drawable", "ic_user_marker")
	userMarker = NeshanMapSdk1.addMarker(userMarkerDrawable,25,location.Latitude,location.Longitude)
	NeshanMapSdk1.moveCamera(location.Latitude,location.Longitude,0.5)
End Sub

Sub GetLocationPermission
	runtimePermissions.CheckAndRequest(runtimePermissions.PERMISSION_ACCESS_FINE_LOCATION)
	Wait for Activity_PermissionResult (Permission As String, Result As Boolean)
	If Result Then
		If isGpsEnabled Then
			'Get user location
			Private LocationRequest1 As LocationRequest
			LocationRequest1.Initialize
			LocationRequest1.SetPriority(LocationRequest1.Priority.PRIORITY_HIGH_ACCURACY)
			fusedLocationProvider1.RequestLocationUpdates(LocationRequest1)
		Else
			NeshanMapSdk1.openGpsSettings
		End If
	Else
		Log("Permission not granted")
	End If
End Sub
        

تابع getLocationSettings توسط شیء fusedLocationProvider یک درخواست برای چک کردن روشن بودن Gps ارسال میکند، پاسخ درخواست در تابعی به نام LocationSettingsChecked ارسال خواهد شد. توسط متغیر locationSettingsResult میتوان وضعیت gps را دریافت کرد.

تابع getLocationPermission جهت گرفتن دسترسی gps است. در صورتی که دسترسی gps از سمت کاربر ارسال شود، تابع RequestLocationUpdates روی شیء fusedLocationProvider صدا زده خواهد شد و شروع به دریافت موقعیت کاربر میکند، در صورتی که موقعیت کاربر دریافت شد، تابع LocationChanged صدا زده میشود و موقعیت کاربر را در متغیر location تحویل میدهد. و در پایان یک مارکر روی نقطه کاربر اضافه میشود.

نکته: در صورتی که ورژن اندروید دستگاه کاربر پایین تر از اندروید 6 باشد حاصل تابع GetLocationPermission همیشه True خواهد بود و فرایند دریافت موقعیت کاربر بدون دریافت دسترسی انجام خواهد شد چرا که دریافت دسترسی از کاربر از اندروید ورژن 6 به بعد در سیستم عامل اندروید پیاده سازی شده است.