Kotlin - lateinit property fragmentHomeBinding has not been initialized - kotlin

I am working on a kotlin application that contains fragments. I am converting an app I created using activity to fragments but I am having an issue. I get an error when running the app that the property fragmentHomeBinding has not been initialized and the app closes.
Here's the fragment Home.kt
class Home : Fragment() {
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient
private lateinit var fragmentHomeBinding: FragmentHomeBinding
#SuppressLint("WrongViewCast")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
getCurrentLocation()
fragmentHomeBinding.etGetCityName.setOnEditorActionListener { v, actionId, keyEvent ->
if(actionId == EditorInfo.IME_ACTION_SEARCH)
{
getCityWeather(fragmentHomeBinding.etGetCityName.text.toString())
val view = activity?.currentFocus
if(view!=null)
{
val imm:InputMethodManager=
activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
fragmentHomeBinding.etGetCityName.clearFocus()
}
true
}
else false
}
}
private fun getCityWeather(cityName:String)
{
fragmentHomeBinding.pbLoading.visibility = View.VISIBLE
ApiUtilities.getApiInterface()?.getCityWeatherData(cityName, API_KEY)?.enqueue(
object:Callback<ModelClass>{
override fun onResponse(call: Call<ModelClass>, response: Response<ModelClass>) {
setDataOnViews((response.body()))
}
override fun onFailure(call: Call<ModelClass>, t: Throwable) {
Toast.makeText(activity?.applicationContext, "Wrong City", Toast.LENGTH_SHORT).show()
}
})
}
private fun getCurrentLocation()
{
if(checkPermission())
{
if(isLocationEnabled())
{
if(ActivityCompat.checkSelfPermission(
requireActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
requireActivity(),
android.Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
){
requestPermission()
return
}
fusedLocationProviderClient.lastLocation.addOnCompleteListener(requireActivity()){ task->
val location: Location?=task.result
if(location==null)
{
fetchCurrentLocationWeather(23.76137119142536.toString(), 90.35059989467042.toString())
}
else
{
fetchCurrentLocationWeather(location.latitude.toString(),location.longitude.toString())
}
}
}
else
{
Toast.makeText(activity?.applicationContext, "Turn on Location", Toast.LENGTH_SHORT).show()
val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
startActivity(intent)
}
}
}
private fun fetchCurrentLocationWeather(latitude: String, longitude:String)
{
fragmentHomeBinding.pbLoading.visibility = View.VISIBLE
ApiUtilities.getApiInterface()?.getCurrentWeatherData(latitude, longitude, API_KEY)?.enqueue(
object : Callback<ModelClass> {
override fun onResponse(call: Call<ModelClass>, response: Response<ModelClass>) {
if(response.isSuccessful)
{
setDataOnViews(response.body())
}
}
override fun onFailure(call: Call<ModelClass>, t: Throwable) {
Toast.makeText(activity?.applicationContext, "ERROR", Toast.LENGTH_SHORT).show()
}
})
}
private fun setDataOnViews(body: ModelClass?) {
val sdf = SimpleDateFormat("dd/MM/yyyy hh:mm")
val currentDate = sdf.format(Date())
fragmentHomeBinding.tvDateTime.text = currentDate
fragmentHomeBinding.tvDayMaxTemp.text = ""+kelvinToCelsius(body!!.main.temp_max) + "°"
fragmentHomeBinding.tvDayMinTemp.text = ""+kelvinToCelsius(body!!.main.temp_min) + "°"
fragmentHomeBinding.tvTemp.text = ""+kelvinToCelsius(body!!.main.temp)
fragmentHomeBinding.tvFeelsLike.text = "Feels like: "+kelvinToCelsius(body!!.main.feels_like) + "°"
fragmentHomeBinding.tvWeatherType.text = body.weather[0].main
fragmentHomeBinding.tvPressure.text = body.main.pressure.toString()
fragmentHomeBinding.tvHumidity.text = body.main.humidity.toString() + " %"
fragmentHomeBinding.tvWindSpeed.text = body.wind.speed.toString() + " m/s"
fragmentHomeBinding.tvCityName.text = body.name
updateUI(body.weather[0].id)
}
private fun updateUI(id: Int) {
fragmentHomeBinding.pbLoading.visibility = View.GONE
fragmentHomeBinding.mainLayout.visibility = View.VISIBLE
}
private fun kelvinToCelsius(temp: Double): Double
{
var intTemp = temp
intTemp = intTemp.minus(273)
return intTemp.toBigDecimal().setScale(1, RoundingMode.UP).toDouble()
}
companion object
{
const val PERMISSION_REQUEST_ACCESS_LOCATION = 100
const val API_KEY = "3c709ccaf2730aa1c263925f75db631a"
}
private fun isLocationEnabled():Boolean{
val locationManager:LocationManager=activity?.getSystemService(Context.LOCATION_SERVICE) as LocationManager
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) || locationManager.isProviderEnabled(
LocationManager.NETWORK_PROVIDER
)
}
private fun requestPermission(){
ActivityCompat.requestPermissions(
requireActivity(), arrayOf(android.Manifest.permission.ACCESS_COARSE_LOCATION,
android.Manifest.permission.ACCESS_FINE_LOCATION),
PERMISSION_REQUEST_ACCESS_LOCATION
)
}
private fun checkPermission():Boolean{
if(ActivityCompat.checkSelfPermission(requireActivity(),
android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(requireActivity(),
android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED)
{
return true
}
return false
}
#Suppress("DEPRECATION")
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if(requestCode== PERMISSION_REQUEST_ACCESS_LOCATION)
{
if(grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(activity?.applicationContext, "Granted", Toast.LENGTH_SHORT).show()
getCurrentLocation()
}
else{
Toast.makeText(activity?.applicationContext, "Denied", Toast.LENGTH_SHORT).show()
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
fragmentHomeBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
// Inflate the layout for this fragment
return fragmentHomeBinding.root
}
}
Here's the error that shows up on logcat:
2022-05-20 17:45:20.582 22026-22048/com.example.weather D/EGL_emulation: app_time_stats: avg=30.74ms min=18.05ms max=34.54ms count=33
2022-05-20 17:45:21.416 22026-22026/com.example.weather D/AndroidRuntime: Shutting down VM
2022-05-20 17:45:21.417 22026-22026/com.example.weather E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.weather, PID: 22026
kotlin.UninitializedPropertyAccessException: lateinit property fragmentHomeBinding has not been initialized
at com.example.weather.Home.onCreate(Home.kt:58)
at androidx.fragment.app.Fragment.performCreate(Fragment.java:2949)
at androidx.fragment.app.FragmentStateManager.create(FragmentStateManager.java:475)
at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:278)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2100)
at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:3138)
at androidx.fragment.app.FragmentManager.dispatchActivityCreated(FragmentManager.java:3072)
at androidx.fragment.app.FragmentController.dispatchActivityCreated(FragmentController.java:251)
at androidx.fragment.app.FragmentActivity.onStart(FragmentActivity.java:502)
at androidx.appcompat.app.AppCompatActivity.onStart(AppCompatActivity.java:246)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1455)
at android.app.Activity.performStart(Activity.java:8076)
at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3660)
at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221)
at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2210)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7839)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
2022-05-20 17:45:21.435 22026-22026/com.example.weather I/Process: Sending signal. PID: 22026 SIG: 9
Help's appreciated, thanks.

Your Fragment viewbinding instance fragmentHomeBinding is initialised at onCreateView() life cycle method. But you are accessing at onCreate() lifecycle method. In Fragment lifecycle, onCreate() will be called before onCreatedView().
As a result you are accessing an object which is not initialised.
To resolve the issue, move your viewbinding reference code in onCreate() to onCreateView() as below.
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
fragmentHomeBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false)
fragmentHomeBinding.etGetCityName.setOnEditorActionListener { v, actionId, keyEvent ->
if(actionId == EditorInfo.IME_ACTION_SEARCH)
{
getCityWeather(fragmentHomeBinding.etGetCityName.text.toString())
val view = activity?.currentFocus
if(view!=null)
{
val imm:InputMethodManager=
activity?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(view.windowToken, 0)
fragmentHomeBinding.etGetCityName.clearFocus()
}
true
}
else false
}
// Inflate the layout for this fragment
return fragmentHomeBinding.root
}

Related

Camera not working on surfaceView once permission is given

class ScanScopeFragment : Fragment() {
private val TAG: String = "ScanScopeFragment"
private lateinit var binding: FragmentScanScopeBinding
private lateinit var mainContext: Context
private lateinit var mainActivity: Activity
private lateinit var surfaceView: SurfaceView
private val REQUEST_CAMERA_PERMISSION = 201
//private val requestCodeCameraPermission = 1001
private lateinit var cameraSource: CameraSource
private lateinit var barcodeDetector: BarcodeDetector
private lateinit var barcodeText: TextView
private var scannedValue = ""
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentScanScopeBinding.inflate(inflater, container, false)
mainContext = requireContext()
mainActivity = requireActivity()
surfaceView = binding.cameraSurfaceView
barcodeText = binding.barcodeText
initialiseDetectorsAndSources()
return binding.root
}
private fun initialiseDetectorsAndSources() {
//Toast.makeText(getApplicationContext(), "Barcode scanner started", Toast.LENGTH_SHORT).show();
barcodeDetector = BarcodeDetector.Builder(mainContext)
.setBarcodeFormats(Barcode.ALL_FORMATS)
.build()
cameraSource = CameraSource.Builder(mainContext, barcodeDetector)
.setRequestedPreviewSize(1920, 1080)
.setAutoFocusEnabled(true) //you should add this feature
.build()
surfaceView.getHolder().addCallback(object : SurfaceHolder.Callback {
override fun surfaceCreated(holder: SurfaceHolder) {
try {
if (ActivityCompat.checkSelfPermission(
mainContext,
Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED
) {
cameraSource.start(surfaceView.getHolder())
} else {
ActivityCompat.requestPermissions(
mainActivity,
arrayOf(Manifest.permission.CAMERA),
REQUEST_CAMERA_PERMISSION
)
}
} catch (e: IOException) {
e.printStackTrace()
}
}
override fun surfaceChanged(
holder: SurfaceHolder,
format: Int,
width: Int,
height: Int
) {
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
cameraSource.stop()
}
})
barcodeDetector.setProcessor(object : Detector.Processor<Barcode> {
override fun release() {
// Toast.makeText(getApplicationContext(), "To prevent memory leaks barcode scanner has been stopped", Toast.LENGTH_SHORT).show();
}
override fun receiveDetections(detections: Detector.Detections<Barcode>) {
val barcodes = detections.detectedItems
if (barcodes.size() != 0) {
barcodeText.post(Runnable {
scannedValue = barcodes.valueAt(0).displayValue
barcodeText.setText(scannedValue)
})
}
}
})
}
/*
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == REQUEST_CAMERA_PERMISSION && grantResults.isNotEmpty()) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initialiseDetectorsAndSources()
} else {
// Toast.makeText(applicationContext, "Permission Denied", Toast.LENGTH_SHORT).show()
}
}
}
*/
override fun onPause() {
super.onPause()
cameraSource.release()
}
override fun onResume() {
super.onResume()
initialiseDetectorsAndSources()
}
}
I am hoping once the permission is given the camera will open on the surfaceView

Synthetics to Viewbinding issues (onBackPress & Navigation Drawer)

I am updating my app to completely remove synthetics and move to viewbinding, however I am struggling with converting the onBackPressed method (now also deprecated) with my Activity, Fragment and Navigation Drawer.
I originally had it like this:
Activity (Before)
override fun onCreate(savedInstanceState: Bundle?) {
Log.d(TAG, "onCreate")
super.onCreate(savedInstanceState)
val activityBinding: BusinessActivityBinding = DataBindingUtil.setContentView(
this,
R.layout.business_activity
)
nav_view.setNavigationItemSelectedListener(this)
val headerView = activityBinding.navView.getHeaderView(0)
headerView.navHeaderEmailText.setOnClickListener { sendSupportEmail() }
navController = findNavController(this, R.id.NavHostFragment)
// other stuff
}
fun openCloseNavigationDrawer() {
if (business_drawer_layout.isDrawerOpen(GravityCompat.START)) {
business_drawer_layout.closeDrawer(GravityCompat.START)
} else {
business_drawer_layout.openDrawer(GravityCompat.START)
}
}
override fun onBackPressed() {
val navHostFragment: NavHostFragment = supportFragmentManager.findFragmentById(R.id.NavHostFragment) as NavHostFragment
val backStackEntryCount = navHostFragment?.childFragmentManager?.backStackEntryCount
when {
(business_drawer_layout.isDrawerOpen(GravityCompat.START)) -> business_drawer_layout.closeDrawer(
GravityCompat.START
)
(backStackEntryCount == 0) -> dialogLeaveApp()
else -> super.onBackPressed()
}
}
private fun dialogLeaveApp(){
MaterialDialog(this).show {
title(R.string.business_activity_dialog_leave_app_heading)
message(R.string.business_activity_dialog_leave_app_message)
positiveButton(R.string.business_activity_dialog_confirm_button){
super.onBackPressed()
}
negativeButton(R.string.business_activity_dialog_cancel_button) {
dismiss()
}
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.nav_sites_fragment -> navigateWithClearStack(R.id.sitesFragment)
R.id.nav_projects_fragment -> navigateWithClearStack(R.id.projectsFragment)
R.id.nav_contacts_fragment -> navigateWithClearStack(R.id.contactsFragment)
R.id.nav_tasks_fragment -> navigateWithClearStack(R.id.tasksFragment)
R.id.nav_profile_fragment -> makeToast("Todo: Profile Fragment")
R.id.nav_settings_fragment -> navigateWithClearStack(R.id.settingsFragment)
}
business_drawer_layout.closeDrawer(GravityCompat.START)
return true
}
private fun navigateWithClearStack(destination: Int) {
businessViewModel.clearCurrentVMData()
val navHostFragment: NavHostFragment = supportFragmentManager.findFragmentById(R.id.NavHostFragment) as NavHostFragment
val inflater = navHostFragment.navController.navInflater
val graph = inflater.inflate(R.navigation.business_navigation)
graph.startDestination = destination
navController.graph = graph
}
}
Fragment (already using viewbinding)
class SitesFragment : Fragment() {
private lateinit var navController: NavController
private lateinit var businessViewModel: BusinessViewModel
private lateinit var sitesAdapter: SitesRecyclerViewAdapter
private var _binding: SitesFragmentBinding? = null // this property is only valid between onCreateView & onDestroyView
private val binding get() = _binding!! //https://stackoverflow.com/questions/57647751/android-databinding-is-leaking-memory
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
Log.d(TAG, "onCreateView()")
activity?.let {
businessViewModel = ViewModelProvider(it).get(BusinessViewModel::class.java)
Log.d(TAG, "businessViewModel = $businessViewModel")
}
Log.d(TAG, businessViewModel.currentStatus("${TAG}, onCreateView()"))
// Inflate the layout for this fragment
_binding = SitesFragmentBinding.inflate(inflater, container, false)
val view = binding.root
binding.apply {
sitesDrawerMenuButton.setOnClickListener {
(activity as BusinessActivity).openCloseNavigationDrawer()
Log.d(TAG, "sitesDrawerMenuButton clicked, openCloseNavigationDrawer()")
}
// Other listeners
}
return view
}
Activity (After)
private var _binding: BusinessActivityBinding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
Log.d(TAG, "onCreate")
super.onCreate(savedInstanceState)
// Inflate the layout for this activity
_binding = BusinessActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
val navHostFragment = supportFragmentManager.findFragmentById(R.id.NavHostFragment) as NavHostFragment
this.navController = navHostFragment.navController
binding.navView.setupWithNavController(this.navController)
// Setup OnBackPressedDispatcher
val backPressedCallback = object:OnBackPressedCallback(false){
override fun handleOnBackPressed() {
onBackButtonPressed()
}
}
// Other stuff
}
fun openCloseNavigationDrawer() { // accessed by Fragment
if (binding.businessDrawerLayout.isDrawerOpen(GravityCompat.START)) {
binding.businessDrawerLayout.closeDrawer(GravityCompat.START)
} else {
binding.businessDrawerLayout.openDrawer(GravityCompat.START)
}
}
fun onBackButtonPressed() {
val navHostFragment: NavHostFragment = supportFragmentManager.findFragmentById(R.id.NavHostFragment) as NavHostFragment
val backStackEntryCount = navHostFragment.childFragmentManager.backStackEntryCount
when {
(binding.businessDrawerLayout.isDrawerOpen(GravityCompat.START)) -> binding.businessDrawerLayout.closeDrawer(
GravityCompat.START
)
(backStackEntryCount == 0) -> dialogLeaveApp()
}
}
private fun dialogLeaveApp(){
// as before
}
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// as before
}
private fun navigateWithClearStack(destination: Int) {
// as before
}
So the issue is that when you back press, it simply exits the app, rather than triggering my function onBackButtonPressed() (which replaces the depricated onBackPressed())and variable 'backPressedCallback' is never used..

FATAL EXCEPTION when Forwarding Intent (URL) in kotlin

---> Full Code for more details https://github.com/BUdiAKmal/CaseApp
After passing URL from "RecyclerView" to Button on "DetailsActivity" , i try to forwarding and load the URL to "WebViewActivity" when user click the "Button on DeetailsActivity".
and finally i get this error :
FATAL EXCEPTION: main
Process: com.caseapp, PID: 5139
java.lang.StackOverflowError: stack size 8MB
at android.os.Parcel.-get0(Unknown Source:0)
at android.os.Parcel$ReadWriteHelper.writeString(Parcel.java:353)
at android.os.Parcel.writeString(Parcel.java:675)
at android.content.ComponentName.writeToParcel(ComponentName.java:320)
at android.content.ComponentName.writeToParcel(ComponentName.java:335)
at android.content.Intent.writeToParcel(Intent.java:9566)
at android.os.Parcel.writeParcelable(Parcel.java:1791)
at android.os.Parcel.writeValue(Parcel.java:1697)
at android.os.Parcel.writeArrayMapInternal(Parcel.java:838)
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1542)
at android.os.Bundle.writeToParcel(Bundle.java:1232)
at android.os.Parcel.writeBundle(Parcel.java:878)
at android.content.Intent.writeToParcel(Intent.java:9599)
at com.caseapp.ui.activities.DetailsActivity.initView$lambda-2$lambda-1(DetailsActivity.kt:68)
at com.caseapp.ui.activities.DetailsActivity.$r8$lambda$JHNmedXwzuffRCNJln7AS9uz4NI(Unknown Source:0)
at com.caseapp.ui.activities.DetailsActivity$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Start - full screen
val window = window
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
) // End - full screen
setUpTabs() // Setup TabLayout
} // End - OnCreate
// Start - TabLayout
private fun setUpTabs() {
val adapter = ViewPagerAdapter(supportFragmentManager)
adapter.addFragment(MainTabFragment1(), "MainTab1")
adapter.addFragment(MainTabFragment1(), "MainTab2")
viewPager_tabLayout.adapter = adapter
tabs.setupWithViewPager(viewPager_tabLayout)
} // End - TabLayout
} // End - Class
MainTabFragment1.kt
class MainTabFragment1 : Fragment() {
lateinit var mainTabFragment1Adapter: MainTabFragment1Adapter // Initialize Adapter
private val sLM = LinearLayoutManager(context) // Initialize layoutManager
val addMainTabFragment1ModelList: MutableList<MainTabFragment1Model> = ArrayList() // Initialize listModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment1_main_tab, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViewMainTabFragment1() // SetUp initView listModel
actionMainTabFragment1() // SetUp actionMainTabFragment1
} // End - OnCreate
// Start - intView listModel
private fun initViewMainTabFragment1() {
rv_mainTabFragment1.layoutManager = sLM
mainTabFragment1Adapter = MainTabFragment1Adapter(requireActivity())
rv_mainTabFragment1.adapter = mainTabFragment1Adapter
addMainTabFragment1ModelList.add(
MainTabFragment1Model(
"https://images.unsplash.com/photo-1585435465945-bef5a93f8849",
"Title RVItemNo.1 MainTabFragment1",
"Desc RVItenNo.1 MainTabFragment1",
"https://google.com"
)
)
addMainTabFragment1ModelList.add(
MainTabFragment1Model(
"https://images.unsplash.com/photo-1487846698364-db1316e3d140",
"Title RVItemNo.2 MainTabFragment1",
"Desc RVItenNo.2 MainTabFragment1",
"https://youtube.com"
)
)
addMainTabFragment1ModelList.add(
MainTabFragment1Model(
"https://images.unsplash.com/photo-1512295767273-ac109ac3acfa",
"Title RVItemNo.3 MainTabFragment1",
"Desc RVItenNo.3 MainTabFragment1",
"https://gmail.com"
)
)
addMainTabFragment1ModelList.add(
MainTabFragment1Model(
"https://images.unsplash.com/photo-1525896969906-0a4806967ef0",
"Title RVItemNo.4 MainTabFragment1",
"Desc RVItenNo.4 MainTabFragment1",
"https://blgger.com"
)
)
mainTabFragment1Adapter.setMainTabFragment1(addMainTabFragment1ModelList)
} // End - intView listModel
// Start - putExtra
fun actionMainTabFragment1() {
mainTabFragment1Adapter.setOnClickItemListenerMainTabFragment1(object : OnItemClickListener {
override fun onItemClick(item: View, position: Int) {
val i = Intent(context, DetailsActivity::class.java)
i.putExtra(
"titleTextMainTabFragment1",
mainTabFragment1Adapter
.getMainTabFragment1()
.get(position)
.titleTextMainTabFragment1
)
i.putExtra(
"descTextMainTabFragment1",
mainTabFragment1Adapter
.getMainTabFragment1()
.get(position)
.descTextMainTabFragment1
)
i.putExtra(
"imgURLMainTabFragment1",
mainTabFragment1Adapter
.getMainTabFragment1()
.get(position)
.imgURLMainTabFragment1
)
i.putExtra(
"btnURLMainTabFragment1",
mainTabFragment1Adapter
.getMainTabFragment1()
.get(position)
.btnURLMainTabFragment1
)
startActivity(i)
}
})
} // End - putExtra
}
DetailsActivity.kt
class DetailsActivity : AppCompatActivity() {
var prodBundle: Bundle? = null // Initialize getString (bundle) from MainActivity
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_details)
// Start - full screen
val window = window
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
) // End - full screen
initView() // Setup getString from RecyclerView Main Activity
} // End - OnCreate
// Start - getString from RecyclerView Main Activity
fun initView() {
prodBundle = intent.extras
tv_titleText.text = prodBundle?.getString("titleTextMainTabFragment1")
tv_descText.text = prodBundle?.getString("descTextMainTabFragment1")
prodBundle?.getString("imgURLMainTabFragment1").let {
Glide.with(this).asBitmap()
.load(it)
.into(iv_imgURL)
Glide.with(this).asBitmap()
.load(it)
.centerCrop()
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
}
prodBundle?.getString("btnURLMainTabFragment1").let {
btn_wvURL.setOnClickListener {
val gotoWebView = Intent(this#DetailsActivity, WebViewActivity::class.java)
gotoWebView.putExtra("btnURLMainTabFragment1", gotoWebView)
startActivity(gotoWebView)
}
}
} // End - getString from RecyclerView Main Activity }
} // End - Class
MainTabFragment1Adapter.kt
class MainTabFragment1Adapter(private val context: Context) :
RecyclerView.Adapter<MainTabFragment1Adapter.MainTabFragment1ViewHolder>() {
private val MainTabFragment1Model: MutableList<MainTabFragment1Model> = mutableListOf() // Initialize listModel
private lateinit var onSelectedListenerMainTabFragment1: OnItemClickListener // Initialize onItemListener
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MainTabFragment1ViewHolder {
return MainTabFragment1ViewHolder(
LayoutInflater.from(context).inflate(R.layout.item_maintab_fragment1_layout, parent, false)
)
} // End - onCreateViewHolder
override fun getItemCount(): Int {
return MainTabFragment1Model.size
} // End - getItem
override fun onBindViewHolder(holder: MainTabFragment1ViewHolder, position: Int) {
holder.maintabfragment1BindView(MainTabFragment1Model[position])
} // End - onBindViewHolder
// Start - setMainTabFragment1
fun setMainTabFragment1(data: List<MainTabFragment1Model>) {
MainTabFragment1Model.clear()
MainTabFragment1Model.addAll(data)
notifyDataSetChanged()
} // End - setMainTabFragment1
// Start - getMainTabFragment1
fun getMainTabFragment1(): MutableList<MainTabFragment1Model> {
return MainTabFragment1Model
} // End - getMainTabFragment1
// Start - MainTabFragment1ViewHolder
inner class MainTabFragment1ViewHolder(maintabfragment1view: View) : RecyclerView.ViewHolder(maintabfragment1view) {
val ivMainTabFragment1 = maintabfragment1view.findViewById<ImageView>(R.id.iv_RVItem_MainTabFragment1)
val tvTitleMainTabFragment1 = maintabfragment1view.findViewById<TextView>(R.id.tv_titleText_MainTabFragment1)
val cvMainTabFragment1: MaterialCardView = maintabfragment1view.findViewById(R.id.cv_RVItem_MainTabFragment1)
fun maintabfragment1BindView(MainTabFragment1Model: MainTabFragment1Model) {
MainTabFragment1Model.apply {
val image = MainTabFragment1Model.imgURLMainTabFragment1
image.let {
Glide.with(itemView.context)
.load(it)
.into(ivMainTabFragment1)
Glide.with(itemView.context)
.load(it)
.centerCrop()
.fitCenter()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.skipMemoryCache(true)
}
}
tvTitleMainTabFragment1.text = MainTabFragment1Model.titleTextMainTabFragment1
}
init {
cvMainTabFragment1.setOnClickListener { onSelectedListenerMainTabFragment1.onItemClick(it, layoutPosition) }
}
} // End - MainTabFragment1BindViewHolder
// Start - OnItemListener
fun setOnClickItemListenerMainTabFragment1(onItemClickListener: OnItemClickListener) {
this.onSelectedListenerMainTabFragment1 = onItemClickListener
} // End - OnItemListener
} // End - Class
MainTabFragment1Model.kt
data class MainTabFragment1Model
(var imgURLMainTabFragment1: String?,
var titleTextMainTabFragment1: String?,
var descTextMainTabFragment1: String?,
val btnURLMainTabFragment1: String?)
Listener.kt
interface OnItemClickListener {
fun onItemClick(item: View, position:Int)
}
WebViewActivity.kt
class WebViewActivity : AppCompatActivity() {
private lateinit var webView: WebView // Initialize WebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_webview)
// Start - Assign Open New URL
val wBS = intent
val webSite = wBS.getStringExtra("btnURLMainTabFragment1")
// End - Assign Open New URL
// Start - full screen
val window = window
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
window.setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
) // End - full screen
// Start - WebView
webView = findViewById(R.id.wv)
webView.setWebViewClient(object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
view?.visibility = View.INVISIBLE
if (Build.VERSION.SDK_INT >= 19) {
webView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
} else {
webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)
}
}
override fun onPageFinished(view: WebView?, url: String?) {
swipe?.isRefreshing = false
super.onPageFinished(view, url)
view?.visibility = View.VISIBLE
}
// Start - Fix Whatsapp Acces
override fun shouldOverrideUrlLoading(wv: WebView, url: String): Boolean {
if (url.startsWith("tel:") || url.startsWith("whatsapp:")) {
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(url)
startActivity(intent)
webView.goBack()
return true
}
return false
} // End - Fix Whatsapp Acces
}) // End - WebView
refreshApp() // SetUp SwipeRefresh
// Start - WebView Setting
if (webSite != null) {
webView.loadUrl(webSite)
}
val webSettings = webView.settings
webSettings.javaScriptEnabled = true // js active
webSettings.domStorageEnabled = true // componenet load
webSettings.allowContentAccess = true
webSettings.loadsImagesAutomatically = true
webSettings.cacheMode = WebSettings.LOAD_NO_CACHE
webSettings.setRenderPriority(WebSettings.RenderPriority.HIGH)
webSettings.setEnableSmoothTransition(true)
// End - WebView Setting
}// End -OnCreate
// Start - BackPressed CurrentView
override fun onBackPressed() {
if (webView.canGoBack()) {
webView.goBack()
} else
super.onBackPressed()
} // End - BackPressed CurrentView
// Start - SwipeRefresh
private fun refreshApp() {
swipe.setOnRefreshListener {
webView?.reload()
Toast.makeText(this, "Refresh!", Toast.LENGTH_SHORT).show()
}
} // End- SwipeRefresh
} // finish MainActivity
I know there must be something wrong in my "DetailsActivity.kt",
especially on this line :
prodBundle?.getString("btnURLMainTabFragment1").let {
btn_wvURL.setOnClickListener {
val gotoWebView = Intent(this#DetailsActivity, WebViewActivity::class.java)
gotoWebView.putExtra("btnURLMainTabFragment1", gotoWebView)
startActivity(gotoWebView)
}
How to solve it?
I hope someone can solve this case. And thanks for taking your time.
Here you are sending the intent as an extra to the intent itself:
val gotoWebView = Intent(this#DetailsActivity, WebViewActivity::class.java)
>>> gotoWebView.putExtra("btnURLMainTabFragment1", gotoWebView)
You can try:
prodBundle?.getString("btnURLMainTabFragment1")?.let { url->
btn_wvURL.setOnClickListener {
val gotoWebView = Intent(this#DetailsActivity, WebViewActivity::class.java)
gotoWebView.putExtra("btnURLMainTabFragment1", url)
startActivity(gotoWebView)
}
This should work.

How can I check if a user has uploaded photos to my image views in Kotlin android

How can I check if a user has uploaded photos to my image views in Kotlin android, so that I can allow them to move to the next fragment. I want to include this in my on Apply function where I have including the other checks for is Null Or Empty for the text views. I have 4 image views I want the user to upload photos to. I want to check this in on apply function.
private lateinit var userId: String
private lateinit var userDatabase: DatabaseReference
private var callback: TinderCallback?=null
fun setCallback(callback: TinderCallback) {
this.callback = callback
userId= callback.onGetUserId()
userDatabase= callback.getUserDatabase().child(userId)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
progressLayout.setOnTouchListener { view, event -> true }
populateInfo()
photoIV.setOnClickListener{callback?.startActivityForPhoto()}
image1IV.setOnClickListener{callback?.startActivityForPhoto1()}
image2IV.setOnClickListener{callback?.startActivityForPhoto2()}
image3IV.setOnClickListener{callback?.startActivityForPhoto3()}
applyButton.setOnClickListener { onApply()}
signoutButton.setOnClickListener{callback?.onSignOut()}
}
fun populateInfo(){
progressLayout.visibility = View.VISIBLE
userDatabase.addListenerForSingleValueEvent(object: ValueEventListener{
override fun onDataChange(snapshot: DataSnapshot) {
if(isAdded){
val user = snapshot.getValue(User::class.java)
nameET.setText(user?.name, TextView.BufferType.EDITABLE)
emailET.setText(user?.email, TextView.BufferType.EDITABLE)
ageET.setText(user?.age, TextView.BufferType.EDITABLE)
occupationET.setText(user?.occupation, TextView.BufferType.EDITABLE)
countryET.setText(user?.country, TextView.BufferType.EDITABLE)
cityET.setText(user?.city, TextView.BufferType.EDITABLE)
interestsET.setText(user?.interests, TextView.BufferType.EDITABLE)
if(user?.gender == GENDER_MALE) {
radioMan1.isChecked = true
}
if (user?.gender == GENDER_FEMALE){
radioWoman1.isChecked = true
}
if(user?.preferredGender == GENDER_MALE) {
radioMan2.isChecked = true
}
if(user?.preferredGender == GENDER_FEMALE){
radioWoman2.isChecked = true
}
if (!user?.imageUrl.isNullOrEmpty()) {
populateImage(user?.imageUrl!!)
}
if (!user?.image1url.isNullOrEmpty()) {
populateImage1(user?.image1url!!)
}
if (!user?.image2url.isNullOrEmpty()) {
populateImage2(user?.image2url!!)
}
if (!user?.image3url.isNullOrEmpty()) {
populateImage3(user?.image3url!!)
}
progressLayout.visibility = View.GONE
}
}
override fun onCancelled(error: DatabaseError) {
progressLayout.visibility = View.GONE
}
})
}
private fun onApply(){
if(nameET.text.toString().isNullOrEmpty() ||
ageET.text.toString().isNullOrEmpty() ||
emailET.text.toString().isNullOrEmpty() ||
radioGroup1.checkedRadioButtonId == -1 ||
radioGroup2.checkedRadioButtonId == -1) {
Toast.makeText(context, getString(R.string.error_profile_incomplete), Toast.LENGTH_SHORT).show()
} else {
val name = nameET.text.toString()
val age = ageET.text.toString()
val email = emailET.text.toString()
val occupation = occupationET.text.toString()
val country = countryET.text.toString()
val city = cityET.text.toString()
val interests = interestsET.text.toString()
val gender =
if(radioMan1.isChecked) GENDER_MALE
else GENDER_FEMALE
val preferredGender =
if(radioMan2.isChecked) GENDER_MALE
else GENDER_FEMALE
userDatabase.child(DATA_NAME).setValue(name)
userDatabase.child(DATA_AGE).setValue(age)
userDatabase.child(DATA_EMAIL).setValue(email)
userDatabase.child(DATA_COUNTRY).setValue(country)
userDatabase.child(DATA_CITY).setValue(city)
userDatabase.child(DATA_OCCUPATION).setValue(occupation)
userDatabase.child(DATA_INTERESTS).setValue(interests)
userDatabase.child(DATA_GENDER).setValue(gender)
userDatabase.child(DATA_GENDER_PREFERRENCE).setValue(preferredGender)
callback?.profileComplete()
}
}
fun updateImageUri(Uri:String){
userDatabase.child(DATA_IMAGE_URL).setValue(Uri)
populateImage(Uri)
}
fun updateImageUri1(Uri:String){
userDatabase.child(DATA_PHOTO1_URL).setValue(Uri)
populateImage1(Uri)
}
fun populateImage(Uri: String) {
Glide.with(this)
.load(Uri)
.into(photoIV)
}
fun populateImage1(Uri: String){
Glide.with(this)
.load(Uri)
.into(image1IV)
}
fun updateImageUri2(Uri:String){
userDatabase.child(DATA_PHOTO2_URL).setValue(Uri)
populateImage2(Uri)
}
fun populateImage2(Uri: String) {
Glide.with(this)
.load(Uri)
.into(image2IV)
}
fun updateImageUri3(Uri:String){
userDatabase.child(DATA_PHOTO3_URL).setValue(Uri)
populateImage3(Uri)
}
fun populateImage3(Uri: String) {
Glide.with(this)
.load(Uri)
.into(image3IV)
}```
If those populateImage functions are where you add the images to the ImageViews, you could set an imageAdded var in there, one for each ImageView. Then your code can check if all 4 are set to true

Capture and show image from camera2 API, Android Studio, Kotlin

I have been following a tutorial on how to get a camera preview on a fragment to show on my app, I am new to kotlin but have been programming in Swift for 2 years. Is there a way to get an image from the preview and show it in another image view.
I created an image view called imageGotCont and this is where I want to place the images I have a button in my main activity so when I press it I need a function that gets an image fromt the preview and places it in the image view.
Below is the fragment.
class FragmentCameraPreview : Fragment() {
private val MAX_DISPLAY_WIDTH = 1280
private val MAX_DISPLAY_HEIGHT = 720
private lateinit var captureSession: CameraCaptureSession
private lateinit var captureRequestBuilder: CaptureRequest.Builder
private lateinit var imageSize: Size
private lateinit var cameraDevice: CameraDevice
private val deviceStateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(camera: CameraDevice?) {
Log.d(TAG, "camera device opened")
if (camera != null) {
cameraDevice = camera
previewSession()
}
}
override fun onDisconnected(camera: CameraDevice?) {
Log.d(TAG, "camera device disconnected")
camera?.close()
}
override fun onError(camera: CameraDevice?, error: Int) {
Log.d(TAG, "camera device error")
this#FragmentCameraPreview.activity?.finish()
}
}
private lateinit var backgroundThread: HandlerThread
private lateinit var backgroundHandler: Handler
private val cameraManager by lazy {
activity?.getSystemService(Context.CAMERA_SERVICE) as CameraManager
}
companion object {
private val TAG = FragmentCameraPreview::class.qualifiedName
const val REQUEST_CAMERA_PERMISSION = 100
#JvmStatic
fun newInstance() = FragmentCameraPreview()
}
private val surfaceListner = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) {
}
override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) = Unit
override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean = true
override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
Log.d(TAG, "Tony texture surface width: $width height: $height")
openCamera()
}
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
#AfterPermissionGranted(REQUEST_CAMERA_PERMISSION)
private fun checkCameraPermission() {
if (EasyPermissions.hasPermissions(activity!!, android.Manifest.permission.CAMERA)) {
Log.d(TAG, "APP has camera permission")
connectCamera()
} else {
EasyPermissions.requestPermissions(
activity!!,
getString(R.string.camera_request_rationale),
REQUEST_CAMERA_PERMISSION,
android.Manifest.permission.CAMERA
)
}
}
override fun onResume() {
super.onResume()
startBackgroundThread()
if (previewTextureView.isAvailable)
openCamera()
else
previewTextureView.surfaceTextureListener = surfaceListner
}
override fun onPause() {
closeCamera()
stopBackgroundThread()
super.onPause()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val myInflatedView = inflater.inflate(R.layout.fragment_camera_preview, container, false)
return myInflatedView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
activity?.window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY or View.SYSTEM_UI_FLAG_FULLSCREEN or
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
}
private fun openCamera() {
checkCameraPermission()
}
private fun <T> cameraCharacteristics(cameraId: String, key: CameraCharacteristics.Key<T>): T {
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
return when (key) {
CameraCharacteristics.LENS_FACING -> characteristics.get(key)
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP -> characteristics.get(key)
else -> throw IllegalArgumentException("Key not recognized")
}
}
private fun cameraId(lens: Int): String {
var deviceId = listOf<String>()
try {
val cameraIdList = cameraManager.cameraIdList
deviceId = cameraIdList.filter { lens == cameraCharacteristics(it, CameraCharacteristics.LENS_FACING) }
} catch (e: CameraAccessException) {
Log.e(TAG, e.toString())
}
return deviceId[0]
}
private fun connectCamera() {
val deviceID = cameraId(CameraCharacteristics.LENS_FACING_BACK)
Log.d(TAG, "deviceID: $deviceID")
try {
cameraManager.openCamera(deviceID, deviceStateCallback, backgroundHandler)
} catch (e: CameraAccessException) {
Log.e(TAG, e.toString())
} catch (e: InterruptedException) {
Log.e(TAG, "Open camera device interrupted while opening")
}
}
private fun startBackgroundThread() {
backgroundThread = HandlerThread("CameraKotlin").also { it.start() }
backgroundHandler = Handler(backgroundThread.looper)
}
private fun stopBackgroundThread() {
backgroundThread.quitSafely()
try {
backgroundThread.join()
} catch (e: InterruptedException) {
Log.e(TAG, e.toString())
}
}
private fun previewSession() {
val surfaceTexture = previewTextureView.surfaceTexture
surfaceTexture.setDefaultBufferSize(MAX_DISPLAY_WIDTH, MAX_DISPLAY_HEIGHT)
val surface = Surface(surfaceTexture)
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE)
captureRequestBuilder.addTarget(surface)
cameraDevice.createCaptureSession(
Arrays.asList(surface),
object : CameraCaptureSession.StateCallback() {
override fun onConfigureFailed(session: CameraCaptureSession?) {
Log.e(TAG, "creating capture session failed")
}
override fun onConfigured(session: CameraCaptureSession?) {
if (session != null) {
captureSession = session
captureRequestBuilder.set(
CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE
)
captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null)
}
}
}, null
)
}
private fun closeCamera() {
if (this::captureSession.isInitialized)
captureSession.close()
if (this::cameraDevice.isInitialized)
cameraDevice.close()
}
}