Android CameraX NoSuchMethodError: No static method getOrCreateInstance(Landroid/content/Context;) - android-studio

I run Android emulator and crash at "cameraProviderFuture = ProcessCameraProvider.getInstance(requireActivity())"
this line.
Why?
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val barcodeScannerOptions = BarcodeScannerOptions.Builder()
.setBarcodeFormats(
Barcode.FORMAT_QR_CODE
)
.build()
cameraProviderFuture = ProcessCameraProvider.getInstance(requireActivity())
cameraProviderFuture.addListener(
Runnable {
val cameraProvider = cameraProviderFuture.get()
val preview = Preview.Builder().build()
val cameraSelector = CameraSelector.Builder()
.requireLensFacing(LENS_FACING_BACK)
.build()
preview.setSurfaceProvider(binding.cargoPreviewView.surfaceProvider)
val camera =
cameraProvider.bindToLifecycle(viewLifecycleOwner, cameraSelector, preview)
},ContextCompat.getMainExecutor(requireContext())
)
}
logcat error:
java.lang.NoSuchMethodError: No static method getOrCreateInstance(Landroid/content/Context;)Lcom/google/common/util/concurrent/ListenableFuture; in class Landroidx/camera/core/CameraX; or its super classes (declaration of 'androidx.camera.core.CameraX' appears in /data/app/~~pfIVQ_AeL7AM1I9N0OVqPw==/-soiV3Uc-nIKoyBDTJx6EHA==/base.apk)
at androidx.camera.lifecycle.ProcessCameraProvider.getInstance(ProcessCameraProvider.java:149)
at com.hannlync.mercury.fragment.information_activity.information_fragment.cargo_fragment.CargoFragment.onViewCreated(CargoFragment.kt:47)

After I updated gradle and solve the problem.
// CameraX core library using the camera2 implementation
def camerax_version = "1.0.2"
// The following line is optional, as the core library is included indirectly by camera-camera2
implementation "androidx.camera:camera-core:1.1.0-alpha11"
implementation "androidx.camera:camera-camera2:1.1.0-alpha11"
// If you want to additionally use the CameraX Lifecycle library
implementation "androidx.camera:camera-lifecycle:1.1.0-alpha11"
// If you want to additionally use the CameraX View class
implementation "androidx.camera:camera-view:1.0.0-alpha31"
// If you want to additionally use the CameraX Extensions library
implementation "androidx.camera:camera-extensions:1.0.0-alpha31"

Related

Hilt - cannot be initialized ViewModelFactory in fragment

i'am using retrofit library to get info from internet api , then i put the data in the repository then get it in viewmodel which it will be instatiate by viewmodelfactory ;
so i'am trying to inject HitViewModelFactory by using Dagger-Hilt in Fragment but it show me an error when to inject it in the fragment
lateinit property hitViewModelFactory has not been initialized
i make an application class and anotate it with #HiltAndroidApp and give the name of application in manifest. and make anotate to activity that host this fragment but the problem not solved
#AndroidEntryPoint
class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
.......
}
}
i provide all dependencies that i need in the module class :
#Module
#InstallIn(ApplicationComponent::class)
object AppModule {
#Singleton
#Provides
fun provideHitPhotoApi() = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(HitApi::class.java)
#Singleton
#Provides
fun provideHitRepository(hitApi: HitApi) = HitRepository(hitApi)
#Singleton
#Provides
fun provideHitViewModelFactory(hitRepository: HitRepository) : HitViewModelFactory = HitViewModelFactory(hitRepository)
}
and try to inject ViewModelFactory in this fragment
#AndroidEntryPoint
class TripsFragment : Fragment() {
#Inject
lateinit var hitViewModelFactory: HitViewModelFactory
lateinit var hitViewModel: HitViewModel
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
hitViewModel = ViewModelProvider(requireActivity(),hitViewModelFactory)[HitViewModel::class.java ]
}
dependency for hilt :
Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.28-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-
alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
I also faced same issue earlier. Not sure why this fails but it seems code is correct.
So I have done with different approach.
I created view model like this below. And I inject HitApi directly in viewmodel constructor. Then just initialize like below. It takes care of creating viewmodel instance and hilt takes care of injection.No need of creating factory.
ViewModel:
#HiltViewModel
class HitViewModel #Inject constructor(
var api: HitApi) : ViewModel() {
}
Fragment:
#AndroidEntryPoint
class TripsFragment : Fragment() {
private val viewModel by viewModels<HitViewModel>() //No need of inject annotation.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
}
Make sure you have these dependancies.
//For activity
implementation 'androidx.activity:activity-ktx:1.5.1'
//For fragment
implementation 'androidx.fragment:fragment-ktx:1.5.1'
the problem solved when i change the dependency of Hilt to :
implementation "com.google.dagger:hilt-android:2.38.1"
kapt "com.google.dagger:hilt-compiler:2.38.1"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha03"
kapt "androidx.hilt:hilt-compiler:1.0.0"
and for these dependencies it should replace the InstallIn anotation for module class to SingletonComponent::class like
#Module
#InstallIn(SingletonComponent::class)
object AppModule { ... }

Instantiating ViewModel that needs application parameter causes a render problem in a composable preview

My preview of a composable is not working and displaying this render problem :
java.lang.ClassCastException: class com.android.layoutlib.bridge.android.BridgeContext cannot be cast to class android.app.Application
My preview code :
#Preview
#Composable
fun MainScreenPrev() {
val context = LocalContext.current
val application = context.applicationContext as Application
val navController = rememberNavController()
val myViewModel = MyViewModel(application)
MainScreen(navController = navController, myViewModel = myViewModel)
}
MyViewModel extends AndroidViewModel that has application as parameter. Most examples online show this as the proper way to get application inside a composable. Is there a better practice to get this preview to work ?

Instanciate Room database in Android Studio

I'm trying to instanciate a Room database in my main activity in Android Studio, following codelabs and tutorials, but my app always crash. Here's a part of the code:
My database (AppDatabase.kt):
#Database(entities = [Device::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun deviceDao(): DeviceDao
companion object {
#Volatile
private var INSTANCE: AppDatabase? = null
fun getDatabase(context: Context): AppDatabase {
return INSTANCE ?: synchronized(this) {
val instance = Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"item_database"
)
.fallbackToDestructiveMigration()
.build() // <---- The crash occurs here
INSTANCE = instance
return instance
}
}
}
}
And here's the activity from which I'm trying to instantiate it:
class NavigationActivity() : AppCompatActivity() {
private lateinit var binding: ActivityNavigationBinding
private val db by lazy { AppDatabase.getDatabase(this) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityNavigationBinding.inflate(layoutInflater)
setContentView(binding.root)
Log.d("instantiation", "$db") // <----- Called from here
val navView: BottomNavigationView = binding.navView
val navController = findNavController(R.id.nav_host_fragment_activity_navigation)
val appBarConfiguration = AppBarConfiguration(
setOf(
R.id.navigation_devices, R.id.navigation_logs, R.id.navigation_settings
)
)
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
}
Finally, here's the error message, which doesn't helps me much:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Package.getName()' on a null object reference
at androidx.room.Room.getGeneratedImplementation(Room.java:82)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:1486)
at AppDatabase$Companion.getDatabase(AppDatabase.kt:24)
I tried a lot of things, including ViewModel, Repository and more, but got the crash systematically, at the same point.
Here's also the part of my build.gradle file where I import Room, maybe I'm wrong in some version or whatever...
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
id 'kotlin-android'
id 'kotlin-kapt'
}
[...]
def roomVersion = "2.4.2"
implementation("androidx.room:room-runtime:$roomVersion")
kapt("androidx.room:room-compiler:$roomVersion")
implementation "androidx.room:room-ktx:$roomVersion"
Make sure package declaration on top of the class is declared, for example:
package com.macrosystems.clean.ui.core.view
import android.content.Context
import android.content.Intent
import android.graphics.Color
etc...

How can I preview a Compose view when it need a parameter in Android Studio?

I can run Code A in Android Studio, I hope to preview UI when I'm designing, so I added Code B to Code A.
But Code B can't work, why? How can I fix it?
Code A
class MainActivity : ComponentActivity() {
private val handleMeter by viewModels<HandleMeter>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
SoundMeterTheme {
Surface(color = MaterialTheme.colors.background) {
Greeting(handleMeter)
}
}
}
}
}
#Composable
fun Greeting(handleMeter: HandleMeter) {
...
}
Code B
#Preview(showBackground = true)
#Composable
fun DefaultPreview() {
SoundMeterTheme {
val handleMeter by viewModels<HandleMeter>()
Greeting(handleMeter)
}
}
Unfortunately, you can't.
Preview does not support creating ViewModels and NavHost yet, for our bad.
But what you can do instead is to use a fake data or a static data into ui, until the design finish and when you are ready to actually run it, replace the static data with the view model data.
You can use dagger and hilt to inject the view model constructor and then call up the hilt view model in the preview e.g.
#HiltViewModel
class DataFieldsViewModel #Inject constructor(
) : ViewModel() {
Then in your preview code for your composable
#Preview(showBackground = true)
#Composable
fun PreviewDataFieldsScreen() {
DataFieldsScreen(
navController = rememberNavController(),
viewModel = hiltViewModel()
)
}

Struggling to transition code from AppcompatActivity to Fragment. Unable to use setSupportActionBar(toolbar)

I'm trying to transition from using AppcomatActivity to Fragment, because I'm updating my app but I've run into a problem. I get a "Unresolved reference: supportFragmentManager" and "Unresolved reference: setSupportActionBar"(That's all the Logcat shows me) when I try to run my app. Now I chose to switch to using fragments, because I also want to change the apps UI, usage is quicker than the previous version. Anyway here's my code:
Recorder Fragment
package com.khumomashapa.notes.fragments
import android.os.Build
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toolbar
import androidx.annotation.RequiresApi
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import androidx.viewpager.widget.ViewPager
import com.astuetz.PagerSlidingTabStrip
import com.khumomashapa.notes.R
import kotlinx.android.synthetic.main.toolbar3.*
class RecorderFragment : Fragment() {
private var tabs: PagerSlidingTabStrip? = null
private var pager: ViewPager? = null
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
activity?.title = "Recorder";
pager = pager?.findViewById<View>(R.id.pager) as ViewPager
pager!!.adapter = MyAdapter(supportFragmentManager)
tabs = tabs?.findViewById<View>(R.id.tabs) as PagerSlidingTabStrip
tabs!!.setViewPager(pager)
val toolbar = toolbar?.findViewById<View>(R.id.toolbar) as Toolbar
toolbar.popupTheme = R.style.ThemeOverlay_AppCompat_Light
setSupportActionBar(toolbar)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_recorder, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
inner class MyAdapter(fm: FragmentManager?) : FragmentPagerAdapter(
fm!!
) {
private val titles = arrayOf(
getString(R.string.tab_title_record),
getString(R.string.tab_title_saved_recordings)
)
override fun getItem(position: Int): Fragment {
when (position) {
0 -> {
return RecordFragment.newInstance(position)
}
1 -> {
return FileViewerFragment.newInstance(position)
}
}
return null!!
}
override fun getCount(): Int {
return titles.size
}
override fun getPageTitle(position: Int): CharSequence? {
return titles[position]
}
}
companion object {
private val LOG_TAG = RecorderFragment::class.java.simpleName
}
}
The purpose of this class is to show a view pager that can switch between to other fragments I've already created. I was able to fix the other errors relating to this like the "Unresolved reference for findViewById" and the "MyAdapter class".
For a Fragment, there are actually two relevant fragment managers. Deciding which one to use depends on your use case.
The Child Fragment Manager
A fragment has a child fragment manager which is responsible for managing its child/nested fragments. You can obtain this with:
Fragment.getChildFragmentManager()
The Parent's Fragment Manager
A fragment also holds reference to it's parent's fragment manager. If the fragment is a direct child of an activity then his represents the activities fragment manager. Otherwise if the fragment is a child of another fragment, it represents the child fragment manager of the parent fragment. This can be obtained with:
Fragment.getParentFragmentManager()
Note that although Fragment has the method Fragment.getFragmentManager(), this is deprecated in favour of Fragment.getParentFragmentManager() so it shouldn't be used.
You can also technically get the activities fragment manager regardless by obtaining a reference to the fragment's activity with Fragment.getAcitivity() and then calling Activity.getSupportFragmentManager(). But generally the parent fragment manager is more useful and clear.

Resources