android mapBox java.lang.Exception: Last location unavailable - android

Integrated mapbox in android.On some devices theres no problem and on some other devices the current location is not being set.It just shows a black screen for mapView.In the devices that not showing the current location in the mapview the Logcat logs this java.lang.Exception: Last location unavailable.Tested in oreo - two devices(in Xiaomi it's showing but in samsung its not) Nougat(HUAWEI DRA-LX2 ) not showing.Thanks in advance.
class HomeFragment : BaseFragment() {
#Inject
lateinit var factory: ViewModelProvider.Factory
lateinit var binding: HomeBinding
var anchorClicked: Boolean = false
private lateinit var mapboxMap: MapboxMap
private lateinit var locationEngine: LocationEngine
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = inflater.bind(R.layout.fragment_home, container)
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
binding.handler = this
binding.lifecycleOwner = viewLifecycleOwner
binding.mapView.onCreate(savedInstanceState)
val navigationView: NavigationView = requireActivity().findViewById(R.id.sideNV)
val headerView = navigationView.getHeaderView(0)
withViewModel<MapViewModel>(factory) {
binding.mapView.getMapAsync { mapBoxMap ->
this#HomeFragment.mapboxMap = mapBoxMap
if (getCurrentTheme())
mapBoxMap.setStyle(Style.TRAFFIC_NIGHT) {
requestPermission(it)
}
else mapBoxMap.setStyle(Style.TRAFFIC_DAY) {
requestPermission(it)
}
}
val auth = FirebaseAuth.getInstance()
if (auth.currentUser != null) {
val auth1 = FirebaseAuth.getInstance()
if (auth1.currentUser != null) {
headerView.userNameTV.text = auth1.currentUser?.displayName
headerView.userEmailTV.text = auth1.currentUser?.email.toString()
Glide.with(requireActivity())
.load(auth1.currentUser?.photoUrl)
.apply(RequestOptions.bitmapTransform(RoundedCorners(14)))
.into(headerView.userPicIV)
}
}
binding.vm = this
getCountries().observe(viewLifecycleOwner, Observer { })
}
}
fun onAnchor() {
var valueAnimator = ValueAnimator()
valueAnimator = if (anchorClicked) {
ValueAnimator.ofFloat(0.5f, 0.75f)
} else {
ValueAnimator.ofFloat(0.75f, 0.5f)
}
valueAnimator.duration = 500
valueAnimator.interpolator = AccelerateDecelerateInterpolator()
valueAnimator.addUpdateListener { valueAnimator ->
val lp = binding.guideline.layoutParams as ConstraintLayout.LayoutParams
// get the float value
lp.guidePercent = valueAnimator.animatedValue as Float
// update layout params
binding.guideline.layoutParams = lp
}
valueAnimator.start()
anchorClicked = !anchorClicked
}
fun requestPermission(style: Style) {
if (!hasPermissions(context!!, permissions)) requestPermissions(permissions, RC_LOCATION)
else enableLocationComponent(style)
}
private fun enableLocationComponent(loadedMapStyle: Style) {
val customLocationComponentOptions = LocationComponentOptions.builder(context!!)
.trackingGesturesManagement(true)
.accuracyColor(ContextCompat.getColor(context!!, R.color.com_facebook_blue))
.build()
val locationComponentActivationOptions =
LocationComponentActivationOptions.builder(context!!, loadedMapStyle)
.locationComponentOptions(customLocationComponentOptions)
.build()
mapboxMap.locationComponent.apply {
activateLocationComponent(locationComponentActivationOptions)
isLocationComponentEnabled = true
cameraMode = CameraMode.TRACKING
renderMode = RenderMode.COMPASS
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == RC_LOCATION) {
if (grantResults.isNotEmpty()
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
enableLocationComponent(mapboxMap.style!!)
}
}
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onStart() {
super.onStart()
mapView?.onStart()
}
override fun onStop() {
super.onStop()
mapView?.onStop()
}
override fun onPause() {
super.onPause()
mapView?.onPause()
}
override fun onLowMemory() {
super.onLowMemory()
mapView?.onLowMemory()
}
override fun onDestroy() {
super.onDestroy()
mapView?.onDestroy()
}
companion object {
const val RC_LOCATION = 10
}
}

Related

Google Map Update Markers Positions with Clusters

Hello I have a fragment with a MapView inside and I need to update the position of his markers every X seconds.
Actually I re-download the data every X seconds then I call "updateAdams" function to relocate all the markers. The problem is that I see the marker move only if I zoom in/zoom out the map, if I don't zoom I don't see the markers move.
How can I solve this?
I tryed to add mGoogleMap.clear() but doing this the markers just disappear and re-appear only if I zoom in/zoom out again.
This is my code (an Adam is a Vehicle):
class GestioneAdamMapFragment : Fragment(),
OnMapReadyCallback,
GetLocationManager.OnLocationUpdateCallback {
private var mGoogleMap: GoogleMap? = null
private lateinit var mGetLocationManager: GetLocationManager
private var mMyLocation: LatLng? = null
private var mAdams: ArrayList<Adam> = ArrayList()
private var mIsFirstInit = true
private var mIdAdamMarkerClicked: Int? = null
private lateinit var mClusterManager: ClusterManager<MarkerClusterItem>
private val mClusterItems = ArrayList<MarkerClusterItem>()
companion object {
fun newInstance(adams: ArrayList<Adam>): GestioneAdamMapFragment {
val mInstance = GestioneAdamMapFragment()
val args = Bundle()
args.putSerializable(KEY_ADAMS, adams)
mInstance.arguments = args
return mInstance
}
fun newInstance() = GestioneAdamMapFragment()
}
//region [#] Override Lifecycle Methods
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_gestione_adam_map, container, false)
initOnCreateView()
MapsInitializer.initialize(requireContext())
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initOnViewCreated(savedInstanceState)
}
override fun onResume() {
mMapView.onResume()
super.onResume()
}
override fun onPause() {
super.onPause()
mMapView.onPause()
}
override fun onDestroy() {
mMapView?.onDestroy()
super.onDestroy()
}
override fun onLowMemory() {
super.onLowMemory()
mMapView.onLowMemory()
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
if(requestCode == REQ_CODE_PERMISSION_LOCATION){
if(grantResults.size > 0x0){
for(res in grantResults){
if(res == PackageManager.PERMISSION_GRANTED){
mMapView.getMapAsync(this)
break
}
}
}
}
}
//endregion
//region [#] Override OnMapReadyCallback Methods
override fun onMapReady(p0: GoogleMap) {
mGoogleMap = p0
initGoogleMap()
if(mAdams.isNotEmpty()){
initListenersAndCluster()
}
if(mMyLocation != null){
var included = false
if(mAdams.isNotEmpty()){
for(adam in mAdams){
if(adam?.getPosizione() != null && adam!!.getPosizione()!!.getLatitude() != null && adam!!.getPosizione()!!.getLongitude() != null){
included = true
}
}
}
if(!included){
mGoogleMap!!.animateCamera(CameraUpdateFactory.newLatLngZoom(mMyLocation!!, 5.0f))
}
}
}
//region [#] Override GetLocationManager.OnLocationUpdateCallback Methods
override fun onLocationUpdated(location: Location?) {
mMyLocation = if(location != null)
LatLng(location.latitude, location.longitude)
else
null
}
//endregion
//region [#] Public Methods
fun setAdams(adams: List<Adam>){
mAdams.clear()
mAdams.addAll(adams)
if(mGoogleMap != null){
initListenersAndCluster()
}
}
fun updateAdams(adams: List<Adam>){
mClusterManager.removeItems(mClusterItems)
mAdams.clear()
mAdams.addAll(adams)
addClusterItems()
}
//endregion
//region [#] Private Methods
private fun initOnCreateView(){
mGetLocationManager = GetLocationManager.initInstance(requireActivity()).setCallback(this)
mGetLocationManager.startLocationUpdates()
}
private fun initOnViewCreated(savedInstanceState: Bundle?){
mMapView.onCreate(savedInstanceState)
try {
MapsInitializer.initialize(requireActivity().applicationContext)
} catch (e: Exception){
BaseEnvironment.onExceptionLevelLow(TAG, e)
}
mMapView.getMapAsync(this)
mibMapType.setOnClickListener{
when (mGoogleMap!!.mapType) {
GoogleMap.MAP_TYPE_NONE, GoogleMap.MAP_TYPE_HYBRID, GoogleMap.MAP_TYPE_SATELLITE -> mGoogleMap!!.mapType = GoogleMap.MAP_TYPE_NORMAL
GoogleMap.MAP_TYPE_NORMAL, GoogleMap.MAP_TYPE_TERRAIN -> mGoogleMap!!.mapType = GoogleMap.MAP_TYPE_HYBRID
}
}
}
private fun initGoogleMap(){
if(ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED){
ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION), REQ_CODE_PERMISSION_LOCATION)
} else {
mGoogleMap?.isMyLocationEnabled = true
}
}
private fun initListenersAndCluster(){
mGoogleMap?.clear()
if(mIsFirstInit){
initClusterManager()
zoomToCenterOfAdams()
initOnClickMarker()
initOnClickMap()
mIsFirstInit = false
initOnClickMarkerLabel()
}
addClusterItems()
}
//endregion
private fun zoomToCenterOfAdams(){
val builder: LatLngBounds.Builder = LatLngBounds.Builder()
var included = false
for(adam in mAdams){
if(adam?.getPosizione() != null && adam!!.getPosizione()!!.getLatitude() != null && adam!!.getPosizione()!!.getLongitude() != null){
builder.include(LatLng(adam!!.getPosizione()!!.getLatitude()!!.toDouble(), adam!!.getPosizione()!!.getLongitude()!!.toDouble()))
included = true
}
}
if(included){
val cu: CameraUpdate = CameraUpdateFactory.newLatLngBounds(builder.build(), resources.getDimensionPixelSize(R.dimen.padding_100dp))
mGoogleMap?.animateCamera(cu)
}
}
private fun initOnClickMarkerLabel(){
mClusterManager.setOnClusterItemInfoWindowClickListener {
var adam: Adam? = null
for(a in mAdams){
if(a.getId() == it.title!!.toInt()){
adam = a
break
}
}
if(adam != null){
startActivity(DettagliAdamActivity.getIntent(requireContext(), adam))
}
}
}
private fun initOnClickMarker(){
mClusterManager.setOnClusterItemClickListener {
mIdAdamMarkerClicked = it.title!!.toInt()
false
}
}
private fun initOnClickMap(){
mGoogleMap?.setOnMapClickListener {
mIdAdamMarkerClicked = null
}
}
private fun initClusterManager(){
mClusterManager = ClusterManager(requireContext(), mGoogleMap)
mClusterManager.markerCollection.setInfoWindowAdapter(InfoWindowAdapter(mAdams, requireContext()))
mClusterManager.renderer = ClusterItemRenderer(requireContext(), mGoogleMap!!, mClusterManager)
mGoogleMap!!.setOnCameraIdleListener(mClusterManager)
}
private fun addClusterItems(){
for(adam in mAdams){
var lat = adam.getPosizione()?.getLatitude()?.toDouble()
var lng = adam.getPosizione()?.getLongitude()?.toDouble()
if(lat != null && lng != null){
val marker = MarkerClusterItem(adam, lat, lng, adam.getId().toString(), "Snippet")
mClusterItems.add(marker)
mClusterManager.addItem(marker)
}
}
}
//endregion
}
Actually I'm solving this problem by zooming in of 0.001, is there a better way to solve this problem?
I'm doing as last line of "updateAdams":
mGoogleMap?.animateCamera(CameraUpdateFactory.newLatLngZoom(mGoogleMap?.cameraPosition?.target!!, mGoogleMap!!.cameraPosition!!.zoom + 0.001f))

How to make a check for entering the correct city when entering

I have a way where when I enter the name of the city, I substitute the name of the city in the api, and everything works fine, but if I enter a non-real city, then nonsense is put in the api accordingly and the application crashes. I would like to make it so that if the city does not exist, that is, I output an error, then Toast "enter the correct name of the city" appears. Thank you in advance
Код:
const val USE_DEVICE_LOCATION = "USE_DEVICE_LOCATION"
const val CUSTOM_LOCATION = "CUSTOM_LOCATION"
class LocationProviderImpl(
private val fusedLocationProviderClient: FusedLocationProviderClient,
context: Context) : PreferenceProvider(context), LocationProvider {
private val appContext = context.applicationContext
override suspend fun hasLocationChanged(lastWeatherLocation: WeatherLocation): Boolean {
val deviceLocationChanged = try {
hasDeviceLocationChanged(lastWeatherLocation)
} catch (e: LocationPermissionNotGrantedException) {
false
}
return deviceLocationChanged || hasCustomLocationChanged(lastWeatherLocation)
}
override suspend fun getPreferredLocationString(): String {
if(isUsingDeviceLocation()) {
try {
val deviceLocation = getLastDeviceLocation()
?: return "${getCustomLocationName()}"
return "${deviceLocation.latitude},${deviceLocation.longitude}"
} catch (e: LocationPermissionNotGrantedException) {
return "${getCustomLocationName()}"
}
}
else {
return "${getCustomLocationName()}"
}
}
private suspend fun hasDeviceLocationChanged(lastWeatherLocation: WeatherLocation): Boolean {
if (!isUsingDeviceLocation())
return false
val deviceLocation = getLastDeviceLocation()
?: return false
// Comparing doubles cannot be done with "=="
val comparisonThreshold = 0.03
return Math.abs(deviceLocation.latitude - lastWeatherLocation.lat) > comparisonThreshold &&
Math.abs(deviceLocation.longitude - lastWeatherLocation.lon) > comparisonThreshold
}
private fun hasCustomLocationChanged(lastWeatherLocation: WeatherLocation): Boolean {
if (!isUsingDeviceLocation()) {
val customLocationName = getCustomLocationName()
return customLocationName != lastWeatherLocation.name
}
return false
}
private fun getCustomLocationName(): String? {
try {
return preferences.getString(CUSTOM_LOCATION, null)
}
catch (e: Exception) {
isUsingDeviceLocation()
}
throw LocationPermissionNotGrantedException()
}
private fun isUsingDeviceLocation(): Boolean {
return preferences.getBoolean(USE_DEVICE_LOCATION, true)
}
#SuppressLint("MissingPermission")
private suspend fun getLastDeviceLocation(): Location? {
return (if (hasLocationPermission())
fusedLocationProviderClient.lastLocation.asDeferred()
else {
throw LocationPermissionNotGrantedException()
}).await()
}
private fun hasLocationPermission(): Boolean {
return ContextCompat.checkSelfPermission(appContext,
android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED
}
}
CurrentWeatherFragment
class CurrentWeatherFragment : ScopedFragment(), KodeinAware, SharedPreferences.OnSharedPreferenceChangeListener {
override val kodein by closestKodein()
private val viewModelFactory: CurrentWeatherViewModelFactory by instance()
private lateinit var viewModel: CurrentWeatherViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.current_weather_fragment, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
loadBannerAd()
viewModel = ViewModelProvider(this, viewModelFactory)
.get(CurrentWeatherViewModel::class.java)
bindUI()
applyDarkModeSetting()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
private fun loadBannerAd() {
MobileAds.initialize(context) {}
mAdViewCurrent = adView
val adRequest = AdRequest.Builder().build()
mAdViewCurrent.loadAd(adRequest)
mAdViewCurrent.adListener = object: AdListener() {
override fun onAdLoaded() {
}
override fun onAdFailedToLoad(adError : LoadAdError) {
// Code to be executed when an ad request fails.
}
override fun onAdOpened() {
// Code to be executed when an ad opens an overlay that
// covers the screen.
}
override fun onAdClicked() {
// Code to be executed when the user clicks on an ad.
}
override fun onAdClosed() {
}
}
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == "GENDER") {
val prefs = sharedPreferences?.getString(key, "1")
when(prefs?.toInt()) {
1->{
bindUI()
}
2->{
bindUIWomen()
}
}
}
applyDarkModeSetting()
}
override fun onDestroy() {
super.onDestroy()
context?.let {
PreferenceManager.getDefaultSharedPreferences(it)
.registerOnSharedPreferenceChangeListener(this)
}
}
private fun applyDarkModeSetting() {
val sharedPreferences = context?.let { PreferenceManager.getDefaultSharedPreferences(it) }
val settingValue = sharedPreferences?.getString("GENDER", null)?.toIntOrNull() ?: 1
val mode = when (settingValue) {
1 -> {bindUI()}
2 -> {bindUIWomen()}
else -> Toast.makeText(context, "Nothing", Toast.LENGTH_LONG).show()
}
}
private fun bindUI() = launch(Dispatchers.Main) {
val currentWeather = viewModel.weather.await()
val weatherLocation = viewModel.weatherLocation.await()
val CurrentWeatherEntries = viewModel.weather.await()
CurrentWeatherEntries.observe(viewLifecycleOwner, Observer { weatherAll ->
if (weatherAll == null){
return#Observer
}
recyclerViewClothes.apply {
layoutManager = LinearLayoutManager(activity)
adapter = ClothesAdapter(weatherAll)
}
})
weatherLocation.observe(viewLifecycleOwner, Observer { location ->
if (location == null) return#Observer
updateLocation(location.name)
updateCityName(location.name)
})
currentWeather.observe(viewLifecycleOwner, Observer {
if(it == null) return#Observer
group_loading.visibility = View.GONE
weatherAll.visibility = View.VISIBLE
updateDateToday()
//updateIsDay(it.isDay)
updateHumidity(it.humidity)
updateTemperature(it.temperature, it.feelsLikeTemperature)
updateCondition(it.conditionText)
updatePressure(it.pressure)
updateWind(it.windSpeed)
updateCloudy(it.cloud)
GlideApp.with(this#CurrentWeatherFragment)
.load("https:${it.conditionIconUrl}")
.into(imageView_condition_icon)
})
refreshApp()
}
private fun List<UnitSpecificCurrentWeatherEntry>.toCurrentWeatherItems() : List<ClothesAdapter> {
return this.map {
ClothesAdapter(it) //ClothesAdapter
}
}
// private fun List<UnitSpecificCurrentWeatherEntry>.toCurrentWeatherItems() : List<ClothesAdapterWomen> {
// return this.map {
// ClothesAdapterWomen(it) //ClothesAdapter
// }
// }
private fun chooseLocalizationUnitAbbreviation(metric: String, imperial: String): String {
return if(viewModel.isMetricUnit) metric else imperial
}
private fun updateLocation(location: String) {
(activity as? AppCompatActivity)?.supportActionBar?.subtitle = getString(R.string.todayTitle)
}
private fun updateDateToday() {
(activity as? AppCompatActivity)?.supportActionBar?.subtitle = getString(R.string.todayTitle)
}
private fun updateCityName(cityName: String) {
textView_cityName.text = cityName
}
}

Exo player fast scroll playing video sound mixed

I am using exoplayer for playing videos .And for this we are used Fragment instance with pagerstateadapter and viewpager2.
But when scroll fast previous played video sound listen in background as well as in screen video means mix the sound in same video player.
Please help me how to solve this.
1.State adapter
class StoriesPagerAdapter(
fragment: Fragment,
val onClick1: VideoItemAdapter.OnItemClicked?,
val onlikeClick: VideoItemAdapter.OnLikeCLicked?,
val onFollowClick: VideoItemAdapter.OnFollowCLicked?,
val ontrendingClick: VideoItemAdapter.OnTrendCLicked?,
val oniconCLick: VideoItemAdapter.OnIconClick?) : FragmentStateAdapter(fragment) {
val dataList:MutableList<Gettrendingvideos.Data.Postlist>=mutableListOf()
override fun getItemCount(): Int {
return dataList.size
}
fun addAll(movies: MutableList<Gettrendingvideos.Data.Postlist>) {
for (movie in movies) {
add(movie)
}
}
fun add(moive: Gettrendingvideos.Data.Postlist) {
dataList.add(moive)
notifyItemInserted(dataList.size - 1)
}
override fun createFragment(position: Int): Fragment {
return StoryViewFragment.newInstance(
onClick1,
onlikeClick,
onFollowClick,
ontrendingClick,
oniconCLick,
dataList[position]
)
}}
2 Fragment
class StoryViewFragment : Fragment(), CommentFragment.onCommentCountIncrease {
private var storyUrl: String? = null
private var storiesDataModel: Gettrendingvideos.Data.Postlist? = null
lateinit var mView: View
private var simplePlayer: SimpleExoPlayer? = null
private var cacheDataSourceFactory: CacheDataSourceFactory? = null
private val simpleCache = MainApplication.simpleCache
private var toPlayVideoPosition: Int = -1
lateinit var viewModel: MainViewModel
lateinit var preferences: SecurePreferences
private var bool: Boolean? = false
var onItemClick: VideoItemAdapter.OnItemClicked? = null
var onlikeCLicked: VideoItemAdapter.OnLikeCLicked? = null
var onFollowCLicked: VideoItemAdapter.OnFollowCLicked? = null
var onTrendCLicked: VideoItemAdapter.OnTrendCLicked? = null
var onIconClick: VideoItemAdapter.OnIconClick? = null
lateinit var huserId: String
lateinit var token: String
companion object {
fun newInstance(
itemClicked: VideoItemAdapter.OnItemClicked?,
likeCLicked: VideoItemAdapter.OnLikeCLicked?,
onFollowCLicked: VideoItemAdapter.OnFollowCLicked?,
onTrendCLicked: VideoItemAdapter.OnTrendCLicked?,
onIconClick: VideoItemAdapter.OnIconClick?,
storiesDataModel: Gettrendingvideos.Data.Postlist
) = StoryViewFragment()
.apply {
arguments = Bundle().apply {
putParcelable(Constants.KEY_STORY_DATA, storiesDataModel)
}
this.onItemClick = itemClicked
this.onlikeCLicked = likeCLicked
this.onFollowCLicked = onFollowCLicked
this.onTrendCLicked = onTrendCLicked
this.onIconClick = onIconClick
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
mView = inflater.inflate(
R.layout.layout_main,
container,
false
)
return mView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProviders.of(this, ViewModelFactory(RetrofitBuilder.apiService))
.get(MainViewModel::class.java)
preferences =
SecurePreferences(
requireActivity(),
AppConstants.preferenceName,
AppConstants.USER_DETAILS,
true
)
storiesDataModel = arguments?.getParcelable(Constants.KEY_STORY_DATA)
setData()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
if (!preferences.getString(AppConstants.USER_ID).equals(null)) {
huserId = preferences.getString(AppConstants.USER_ID)!!
Log.d("TAG", "onActivityCreated: $huserId")
}
}
#SuppressLint("SetTextI18n")
private fun setData() {
Log.d("TAG", "setData: $storiesDataModel")
mView.textview2.text = storiesDataModel?.user_name
mView.like_count.text = storiesDataModel?.total_likes.toString()
comment_count.text = storiesDataModel?.total_comments.toString()
mView.textview.text = storiesDataModel?.type
Glide.with(this).load(storiesDataModel?.user_profile_pic).placeholder(R.drawable.profile).into(mView.image)
if (storiesDataModel?.is_like == 0) {
mView.imageView4.setImageResource(R.drawable.ic_like)
} else {
mView.imageView4.setImageResource(R.drawable.ic_like_red)
}
if (storiesDataModel?.is_following!! == 0) {
mView.textview3.text = "Follow"
} else {
mView.textview3.text = "Following"
}
if (storiesDataModel?.user_id.toString()==preferences.getString(AppConstants.USER_ID)) {
mView.textview3.visibility = View.GONE
}
image.setOnClickListener {
if (preferences.getString(AppConstants.token).equals(null)) {
MainActivity().show(childFragmentManager, "")
} else {
preferences.put(
AppConstants.OtherProfile_UserId,
storiesDataModel?.user_id.toString()
)
}
}
val simplePlayer = getPlayer()
player_view_story.player = simplePlayer player_view_story.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FILL)
simplePlayer?.setVideoScalingMode(C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
storyUrl = storiesDataModel?.video_url
prepareMedia(storiesDataModel)
}
override fun onPause() {
pauseVideo()
super.onPause()
}
override fun onResume() {
restartVideo()
super.onResume()
}
override fun onDestroy() {
releasePlayer()
super.onDestroy()
}
private fun pausePlayer() {
simplePlayer?.setPlayWhenReady(false)
simplePlayer?.getPlaybackState()
}
private fun startPlayer() {
simplePlayer?.setPlayWhenReady(true)
simplePlayer?.getPlaybackState()
}
private val playerCallback: Player.EventListener? = object : Player.EventListener {
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
}
override fun onPlayerError(error: com.google.android.exoplayer2.ExoPlaybackException?) {
super.onPlayerError(error)
}
}
private fun prepareVideoPlayer() {
simplePlayer = ExoPlayerFactory.newSimpleInstance(context)
cacheDataSourceFactory = CacheDataSourceFactory(
simpleCache,
DefaultHttpDataSourceFactory(
Util.getUserAgent(
context,
"exo"
)
)
)
}
private fun getPlayer(): SimpleExoPlayer? {
if (simplePlayer == null) {
prepareVideoPlayer()
}
return simplePlayer
}
private fun prepareMedia(datamodel: Gettrendingvideos.Data.Postlist?{
val uri = Uri.parse(datamodel?.video_url)
simplePlayer.repeatMode = Player.REPEAT_MODE_ONE
simplePlayer.playWhenReady = true
if (storiesDataModel!!.type == "following") {
following_page.typeface = Typeface.DEFAULT_BOLD
trending_page.setTypeface(null, Typeface.NORMAL)
} else {
following_page.setTypeface(null, Typeface.BOLD)
}
if (storiesDataModel.type == "treading") {
trending_page.typeface = Typeface.DEFAULT_BOLD
following_page.setTypeface(null, Typeface.NORMAL)
} else {
trending_page.setTypeface(null, Typeface.BOLD)
}
if (simplePlayer.playWhenReady == true) {
}
simplePlayer.addListener(playerCallback)
toPlayVideoPosition = -1
}
private fun setArtwork(drawable: Drawable, playerView: PlayerView) {
playerView.useArtwork = true
playerView.defaultArtwork = drawable
}
private fun playVideo() {
simplePlayer.playWhenReady = true
}
private fun restartVideo() {
if (simplePlayer == null) {
prepareMedia(storiesDataModel)
} else {
simplePlayer.seekToDefaultPosition()
simplePlayer.playWhenReady = true
}
}
private fun pauseVideo() {
simplePlayer.playWhenReady = false
}
private fun releasePlayer() {
simplePlayer.stop(true)
simplePlayer.release()
}}
override fun setMenuVisibility(menuVisible: Boolean) {
if (!menuVisible){
simplePlayer?.playWhenReady = false
simplePlayer?.pause()
}
super.setMenuVisibility(menuVisible)
}
JUST ADD THIS IN YOUR StoryViewFragment.

MapBox 9.2.0 causing crash in Android 8.0 (Oreo) JNI DETECTED ERROR IN APPLICATION

There was no problem, but as it went to background after 3 or 5 mins, the app gets crashed
JNI DETECTED ERROR IN APPLICATION: can't call java.lang.Object java.lang.ref.Reference.get() on instance of java.lang.String in call to CallObjectMethodV from void android.os.MessageQueue.nativePollOnce(long, int) and this is what it is showing in the log.
class HomeFragment : BaseFragment() {
#Inject
lateinit var factory: ViewModelProvider.Factory
lateinit var binding: HomeBinding
var anchorClicked: Boolean = false
private lateinit var mapboxMap: MapboxMap
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = inflater.bind(R.layout.fragment_home, container)
return binding.root
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
binding.handler = this
binding.lifecycleOwner = viewLifecycleOwner
binding.mapView.onCreate(savedInstanceState)
val navigationView: NavigationView = requireActivity().findViewById(R.id.sideNV)
val headerView = navigationView.getHeaderView(0)
withViewModel<MapViewModel>(factory) {
binding.mapView.getMapAsync { mapBoxMap ->
this#HomeFragment.mapboxMap = mapBoxMap
if (getCurrentTheme())
mapBoxMap.setStyle(Style.TRAFFIC_NIGHT){
requestPermission(it)
}
else mapBoxMap.setStyle(Style.TRAFFIC_DAY){
requestPermission(it)
}
}
val auth = FirebaseAuth.getInstance()
if (auth.currentUser != null) {
val auth1 = FirebaseAuth.getInstance()
if (auth1.currentUser != null) {
headerView.userNameTV.text = auth1.currentUser?.displayName
headerView.userEmailTV.text = auth1.currentUser?.email.toString()
Glide.with(requireActivity())
.load(auth1.currentUser?.photoUrl)
.apply(RequestOptions.bitmapTransform(RoundedCorners(14)))
.into(headerView.userPicIV)
}
}
binding.vm = this
getCountries().observe(viewLifecycleOwner, Observer { })
}
}
fun requestPermission(style:Style) {
if (!hasPermissions(context, permissions)) requestPermissions(permissions, RC_LOCATION)
else enableLocationComponent(style)
}
private fun enableLocationComponent(loadedMapStyle: Style) {
val customLocationComponentOptions = LocationComponentOptions.builder(context!!)
.trackingGesturesManagement(true)
.accuracyColor(ContextCompat.getColor(context!!, R.color.com_facebook_blue))
.build()
val locationComponentActivationOptions =
LocationComponentActivationOptions.builder(context!!, loadedMapStyle)
.locationComponentOptions(customLocationComponentOptions)
.build()
mapboxMap.locationComponent.apply {
activateLocationComponent(locationComponentActivationOptions)
isLocationComponentEnabled = true
cameraMode = CameraMode.TRACKING
renderMode = RenderMode.COMPASS
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == RC_LOCATION) {
if (grantResults.isNotEmpty()
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
enableLocationComponent(mapboxMap.style!!)
}
}
}
companion object {
const val RC_LOCATION = 10
}
}
This is my code.Is this some kind of restriction in oreo/an issue with map box.If so what can be done to avoid this.Can we use Coroutines to solve this issue?

ViewPager with FragmentStatePagerAdapter scrolls before closing

I have a ViewPager with a FragmentStatePagerAdapter to let users scroll through videos using a VideoView. It works fine, but when you press the back button, the viewpager scrolls to the left and briefly shows the previous ViewView before closing the viewpager activity.
I understand the FragmentStatePagerAdapter will cache the fragments/views for better memory management, but it seems odd to show the precious view before closing. Is this normal, or is there any way to make sure a view is completely hidden when it's not the current pager in focus?
Here's the code for my Adapter. Basically I return one of two fragments that creates a view with that photo or video in it.
inner class MyAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
override fun getCount(): Int = photoInfo.size
override fun getItemPosition(`object`: Any?): Int = super.getItemPosition(`object`)
override fun getItem(position: Int): Fragment {
when (photoInfo[position].type) {
PHOTO -> {
return PhotoFragment.newInstance(photoInfo[position])
}
VIDEO-> {
return VideoFragment.newInstance(photoInfo[position])
}
else -> {
return PhotoFragment.newInstance(photoInfo[position])
}
}
}
}
And the videofragment:
class VideoFragment : Fragment(), AnkoLogger {
internal var photo: String? = null
internal var totalSize: Int? = null
internal var thumbnail: String? = null
var player: SimpleExoPlayer? = null
var simpleExoPlayerView: SimpleExoPlayerView? = null
var error = false
var shouldLoop = true
var autoPlay = true
var proxy: HttpProxyCacheServer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
photo = arguments.getString("photo")
thumbnail = arguments.getString("thumbnail")
totalSize = arguments.getInt("size")
shouldLoop = defaultSharedPreferences.getBoolean("loop_webm_preference", true)
autoPlay = defaultSharedPreferences.getBoolean("autplay_webm_preference", true)
proxy = getProxy(activity)
}
override fun onDestroyView() {
player?.release()
super.onDestroyView()
}
override fun onPause() {
super.onPause()
}
fun checkAndSetVolume() {
val isMuted = defaultSharedPreferences.getBoolean("mute_video", false)
when (isMuted) {
true -> {
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.imageResource = R.drawable.volume_on
player?.volume = 0f
}
false -> {
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.imageResource = R.drawable.volume_off
player?.volume = 1f
}
}
}
override fun getUserVisibleHint(): Boolean {
return super.getUserVisibleHint()
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
if (!isVisibleToUser) {
player?.playWhenReady = false
player?.playbackState
player?.seekTo(0)
} else if (isVisible && isVisibleToUser && (proxy?.isCached(photo) == true) && !error) {
checkAndStartAutoplay()
}
}
fun checkAndStartAutoplay() {
checkAndSetVolume()
player?.playWhenReady = autoPlay
player?.playbackState
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
simpleExoPlayerView = SimpleExoPlayerView(context)
val mainHandler = Handler()
val bandwidthMeter = DefaultBandwidthMeter()
val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(bandwidthMeter)
val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory)
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector)
val fl = FrameLayout(context)
simpleExoPlayerView?.player = player
simpleExoPlayerView?.setShutterBackgroundColor(Color.TRANSPARENT)
player?.repeatMode = if (shouldLoop) 1 else 0
player?.addListener(object : Player.DefaultEventListener() {
override fun onPlayerError(error: ExoPlaybackException?) {
val tv = TextView(context)
tv.text = getString(android.R.string.VideoView_error_text_unknown)
tv.textColor = Color.WHITE
tv.textAlignment = TextView.TEXT_ALIGNMENT_CENTER
fl.addView(tv, FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.CENTER))
this#VideoFragment.error = true
}
override fun onLoadingChanged(isLoading: Boolean) {
super.onLoadingChanged(isLoading)
if (!isLoading) {
if (this#VideoFragment.isVisible && this#VideoFragment.userVisibleHint) {
checkAndStartAutoplay()
}
}
}
})
val proxyUrl = proxy?.getProxyUrl(photo)
val dataSourceFactory = DefaultDataSourceFactory(context, Util.getUserAgent(context, "Omnichan"), bandwidthMeter)
val videoSource = ExtractorMediaSource.Factory(dataSourceFactory).createMediaSource(Uri.parse(proxyUrl))
player?.prepare(videoSource)
fl.addView(simpleExoPlayerView, FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER))
simpleExoPlayerView?.findViewById<ImageButton>(R.id.exo_mute)?.setOnClickListener {
val isMuted = defaultSharedPreferences.getBoolean("mute_video", false)
defaultSharedPreferences.edit().putBoolean("mute_video", !isMuted).apply()
checkAndSetVolume()
}
return fl
}
companion object {
internal fun newInstance(photoInfo: PhotoInfo): VideoFragment {
val f = VideoFragment()
val args = Bundle()
args.putString("photo", photoInfo.photoUrl)
args.putString("thumbnail", photoInfo.thumbnailUrl)
f.arguments = args
return f
}
private var sharedProxy: HttpProxyCacheServer? = null
private fun newProxy(context: Context): HttpProxyCacheServer {
return HttpProxyCacheServer.Builder(context)
.maxCacheSize((1024 * 1024 * 256).toLong()) // 256 Mb for cache
.build()
}
fun getProxy(context: Context): HttpProxyCacheServer {
return sharedProxy ?: newProxy(context)
}
}
}

Categories

Resources