How to fix crash : ExoPlayer cast extension on Android 9 - android

I have a crash in production since I've have release the ability to cast HLS video from my app to a Chromecast using the ExoPlayer Cast Extension.
It happens 100% on Android 9 and on a variety of devices (Xiaomi Redmi K20, Samsung
Galaxy S9, ZenFone Max Pro M2 etc...)
Here is my ExoPlayer cast extension implementation :
private fun initCast() {
mediaRouteButton = view?.findViewById(R.id.media_route_button)
CastButtonFactory.setUpMediaRouteButton(activity?.applicationContext, mediaRouteButton)
val castContext = CastContext.getSharedInstance()
}
private fun prepareCast(title: String) {
CastContext.getSharedInstance()?.let {
castPlayer = CastPlayer(it)
}
val movieMetadata = MediaMetadata(MediaMetadata.MEDIA_TYPE_MOVIE)
movieMetadata.putString(MediaMetadata.KEY_TITLE, title)
videoThumbnail?.let {
movieMetadata.addImage(WebImage(Uri.parse(it)))
}
val mediaInfo = MediaInfo.Builder(videoUrl)
.setStreamType(MediaInfo.STREAM_TYPE_BUFFERED)
.setContentType(MimeTypes.VIDEO_UNKNOWN)
.setMetadata(movieMetadata).build()
val mediaItems = arrayOf(MediaQueueItem.Builder(mediaInfo).build())
castPlayer?.setSessionAvailabilityListener(object : SessionAvailabilityListener {
override fun onCastSessionAvailable() {
castPlayer?.loadItems(mediaItems, 0, playerViewModel.getVideoPosition(), Player.REPEAT_MODE_OFF)
playerViewModel.pauseVideo()
}
override fun onCastSessionUnavailable() {
castPlayer?.currentPosition?.let {
playerViewModel.setVideoPosition(it)
playerViewModel.playVideo()
}
})
}
Here is the stacktrace :
Fatal Exception: java.lang.NullPointerException: Attempt to write to field 'boolean kj1.a' on a null object reference
at com.google.android.gms.internal.cast.zzka.zzhx(zzka.java:38)
at com.google.android.gms.internal.cast.zzmd.zza(zzmd.java:3)
at com.google.android.gms.internal.cast.zzms.zze(zzms.java:2518)
at com.google.android.gms.internal.cast.zzlf$zza.zziw(zzlf.java:20)
at com.google.android.gms.internal.cast.zzlf$zza.zziy(zzlf.java:41)
at com.google.android.gms.internal.cast.zzlf$zza.zzix(zzlf.java:23)
at com.google.android.gms.internal.cast.zzlf$zza.zziz(zzlf.java:42)
at com.google.android.gms.internal.cast.zzbc.zza(zzbc.java:1)
at com.google.android.gms.internal.cast.zzba.onSessionStarting(zzba.java:49)
at com.google.android.gms.cast.framework.zzag.zza(zzag.java:10)
at com.google.android.gms.cast.framework.zzz.dispatchTransaction(zzz.java:13)
at com.google.android.gms.internal.cast.zza.onTransact(zza.java:13)
at android.os.Binder.transact(Binder.java:667)
at androidx.mediarouter.media.MediaRouter$GlobalMediaRouter$MediaSessionRecord$1$2.b(MediaRouter.java:14)
at androidx.mediarouter.media.RegisteredMediaRouteProvider$Connection$1.a(RegisteredMediaRouteProvider.java:39)
at com.bumptech.glide.load.resource.gif.GifFrameLoader.b(GifFrameLoader.java:50)
at com.bumptech.glide.manager.TargetTracker.a(TargetTracker.java:42)
at androidx.media.AudioAttributesImpl.c(AudioAttributesImpl.java:21)
at androidx.fragment.app.FragmentState.a(FragmentState.java:11)
at androidx.preference.PreferenceGroupAdapter.onTransact(PreferenceGroupAdapter.java:5)
at android.os.Binder.transact(Binder.java:667)
at com.google.android.gms.internal.cast.zzb.zzb(zzb.java:21)
at com.google.android.gms.internal.cast.zzaf.zzd(zzaf.java:21)
at com.google.android.gms.internal.cast.zzaq.onRouteSelected(zzaq.java:4)
at androidx.mediarouter.media.MediaRouter$GlobalMediaRouter$CallbackHandler.invokeCallback(MediaRouter.java:3218)
at androidx.mediarouter.media.MediaRouter$GlobalMediaRouter$CallbackHandler.handleMessage(MediaRouter.java:3168)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6745)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I have open an issue in the ExoPlayer github and in Glide github without luck.
Do anybody have an idea of the cause of this crash ?

Related

How to request API using Retrofit in a Foreground Service in Android 12(Api 31)?

My app has a specific requirement of uploading files as multipart using retrofit and LiveData in the background(App Navigation works while uploading data to the server.). The app requires chained network requests on the bases of the response it gets. I've used the Foreground service for network requests. this procedure works well in Android 9,10,11.
UploadFragment.kt
class UploadFragment : BaseFragment() {
....
private fun uploadFilesToServer() {
val intent = Intent(requireActivity(), MyFileUploadingService::class.java)
ContextCompat.startForegroundService(requireActivity(), intent)
}
}
FileUploadService.kt
class FileUploadService : LifecycleService() {
....
private fun registerObservers() {
viewModel?.uploadLiveData!!.observe(this) { response ->
val dataResponse: DataUploadResponse = response.responseBody!!.data!!
if (dataResponse.error == null) {
....
// Repeat
} else {
stopSelf()
}
}
}
}
I'm getting an error while observing response using LiveData.
val dataResponse: DataUploadResponse = response.responseBody!!.data!!
Error Log
2022-08-24 13:08:59.792 26140-26140/com.myapp.demo E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.myapp.demo, PID: 26140
java.lang.NullPointerException
at com.myapp.demo.service.FileUploadService$registerObservers$1.onChanged(FileUploadService.kt:242)
at com.myapp.demo.service.FileUploadService$registerObservers$1.onChanged(FileUploadService.kt:54)
at androidx.lifecycle.LiveData.considerNotify(LiveData.java:133)
at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:151)
at androidx.lifecycle.LiveData.setValue(LiveData.java:309)
at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:50)
at androidx.lifecycle.LiveData$1.run(LiveData.java:93)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7870)
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)

Showing dialog in MVVM Android throws exception only when certain variable changes in the ViewModel

I have a MainActivity using a DrawerLayout and tabs with 2 fragments.
My first fragment contains a list of elements in a RecyclerView, and I can click on each element to "select" it (which calls a SDK function to login to a hardware device). When selected, this triggers a change on the Fragment's ViewModel:
// Selected device changes when an item is clicked
private val _devices = MutableLiveData<List<DeviceListItemViewModel>>()
private val _selectedDevice = MutableLiveData<ConnectedDevice>()
val devices: LiveData<List<DeviceListItemViewModel>> by this::_devices
val selectedDevice: LiveData<ConnectedDevice> by this::_selectedDevice
Then I have a shared ViewModel between both fragments, which also has a currentDevice variable like this:
private val _currentDevice = MutableLiveData<ConnectedDevice>()
val currentDevice: LiveData<ConnectedDevice> by this::_currentDevice
So in the Fragment that contains the list, I have the following code to update the shared ViewModel variable:
private val mViewModel: DeviceManagementViewModel by viewModels()
private val mSharedViewModel: MainActivityViewModel by activityViewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
Log.d(classTag, "Fragment view created")
val binding = ActivityMainDevicesManagementFragmentBinding.bind(view)
binding.apply {
viewModel = mViewModel
lifecycleOwner = viewLifecycleOwner
}
// Observe fragment ViewModel
// If any device is clicked on the list, do the login on the shared ViewModel
mViewModel.selectedDevice.observe(this, {
mSharedViewModel.viewModelScope.launch {
if (it != null) {
mSharedViewModel.setCurrentDevice(videoDevice = it)
} else mSharedViewModel.unsetCurrentDevice()
}
})
}
The problem is that if the shared ViewModel's currentDevice variable is set, I get exceptions whenever I try to open a Dialog or start a new activity. If I modify the setCurrentDevice function in the shared ViewModel, then it works fine (or if I don't select any device).
The exceptions I see are this when starting a new Activity:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.placeholder.easyview/com.example.myapp.activities.settings.SettingsActivity}: java.lang.IllegalArgumentException: display must not be null
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3430)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3594)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
Caused by: java.lang.IllegalArgumentException: display must not be null
at android.app.ContextImpl.createDisplayContext(ContextImpl.java:2386)
at android.content.ContextWrapper.createDisplayContext(ContextWrapper.java:977)
at com.android.internal.policy.DecorContext.<init>(DecorContext.java:50)
at com.android.internal.policy.PhoneWindow.generateDecor(PhoneWindow.java:2348)
at com.android.internal.policy.PhoneWindow.installDecor(PhoneWindow.java:2683)
at com.android.internal.policy.PhoneWindow.getDecorView(PhoneWindow.java:2116)
at androidx.appcompat.app.AppCompatActivity.initViewTreeOwners(AppCompatActivity.java:219)
at androidx.appcompat.app.AppCompatActivity.setContentView(AppCompatActivity.java:194)
at com.example.myapp.activities.settings.SettingsActivity.onCreate(SettingsActivity.kt:34)
at android.app.Activity.performCreate(Activity.java:8000)
at android.app.Activity.performCreate(Activity.java:7984)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1310)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3403)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3594) 
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85) 
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067) 
at android.os.Handler.dispatchMessage(Handler.java:106) 
at android.os.Looper.loop(Looper.java:223) 
at android.app.ActivityThread.main(ActivityThread.java:7698) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952) 
And this if I try to open a Dialog:
java.lang.ArrayIndexOutOfBoundsException: length=16; index=2448
at android.view.InsetsState.peekSource(InsetsState.java:374)
at android.view.InsetsSourceConsumer.updateSource(InsetsSourceConsumer.java:291)
at android.view.InsetsController.updateState(InsetsController.java:654)
at android.view.InsetsController.onStateChanged(InsetsController.java:621)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:1058)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:409)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:110)
at android.app.Dialog.show(Dialog.java:340)
at android.app.AlertDialog$Builder.show(AlertDialog.java:1131)
at com.example.myapp.activities.main.fragments.DeviceManagementFragment.showAddDeviceMethodDialog(DeviceManagementFragment.kt:151)
at com.example.myapp.activities.main.fragments.DeviceManagementFragment.access$showAddDeviceMethodDialog(DeviceManagementFragment.kt:33)
at com.example.myapp.activities.main.fragments.DeviceManagementFragment$onViewCreated$$inlined$apply$lambda$1.onClick(DeviceManagementFragment.kt:52)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28309)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7698)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952)
EDIT: Looks like the problem actually lies in the other fragment, where I have the following code (in onViewCreated method):
// If the shared view model device changes, this must change too
mSharedViewModel.currentDevice.observe(this, {
if (it != null) {
mViewModel.setCurrentDevice(it)
} else mViewModel.unsetCurrentDevice()
})
mViewModel.currentDevice.observe(this, {
if (it != null) {
mViewModel.fetchChannels()
}
})
If I comment out the second part (where the fetchChannels occurs), it works well. Even if I comment out the fetchChannels call only, it works.
This is the code of the fetchChannels function:
fun fetchChannels() = viewModelScope.launch {
Log.d(classTag, "Getting channels for device ${currentDevice.value}")
currentDevice.value?.let {
val fetchedChannels = deviceLibManager.getChannels(it.videoDevice)
_currentDevice.value?.channels?.clear()
_currentDevice.value?.channels?.addAll(fetchedChannels)
if (fetchedChannels.isNotEmpty()) {
_currentDevice.value?.currentChannel = fetchedChannels[0]
}
}
}
The following line is the one giving me trouble:
val fetchedChannels = deviceLibManager.getChannels(it.videoDevice)
That function is just this:
suspend fun getChannels(videoDevice: VideoDevice): List<VideoChannel> {
try {
Log.i(classTag, "Getting channels from device ${videoDevice}")
val channels = videoDevice.getChannelsAsync()
return channels
} catch (exception: Exception) {
when (exception) {
is UnknownVendorException -> {
Log.w(classTag, "Device ${videoDevice} cannot get channels because the vendor is unknown")
}
is NetworkException -> {
Log.w(classTag, "Device ${videoDevice} cannot get channels because it is unreachable")
}
else -> {
Log.w(classTag, "Device ${videoDevice} cannot get channels, reason: ${exception.message}")
}
}
return emptyList()
}
}
And the implementation in the SDK is this:
override suspend fun getChannelsAsync(): List<VideoChannel> = withContext(Dispatchers.IO) {
Log.i(classTag, "Trying to get channels for device: $logName")
val channels = ArrayList<VideoChannel>()
getZeroChannel()?.let {
channels.add(it)
}
channels.addAll(getAllChannels())
if (channels.isNotEmpty()) {
Log.i(classTag, "Successfully retrieved ${channels.size} channels for device: $logName")
return#withContext channels
} else {
Log.w(classTag, "Error retrieving channels for device $logName or no channels exist")
throw Exception()
}
}
The other functions just make a network call and retrieve some data, it should not be messing with the UI at all.
I am testing with a Xiaomi Mi A3 using Android 10.
Can someone help me? Thank you.
So I don't really know why but I found the answer.
In the SDK, the functions getZeroChannel and getAllChannels were not suspending functions, although they make a network call. So what I did is:
Move the withContext(Dispatchers.IO) part to those two functions (the ones who actually make the network call), and make them suspend functions.
Remove the withContext(Dispatchers.IO) part from getChannelsAsync function. Keep it as a suspend function though.
After these changes everything works as expected. I still don't know why, so if someone could shed some light, that would be very much appreciated.

App Crashing while adding a member in an Private channel in Twilio Chat SDK

I am implementing Twilio Chat SDK where I do add members in a private Channel. The flow goes like this that First I check whether is there a channel in my list or not. If it exists then I join it. And if there is no channel in my list I First create it and then join and it and then add member with it's unique name. When I run my application the Client is created and after the channel process is done it crashes with the following error:
com.twilio.chat.ListenerException: Exception thrown by a listener. Your application might have a problem in listener implementation. Listeners must never throw uncaught exceptions. See 'Caused by:' below for more details.
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at com.twilio.chat.internal.RethrowingForwarder$RethrowingProxy.invoke(RethrowingForwarder.java:123)
at java.lang.reflect.Proxy.invoke(Proxy.java:1006)
at $Proxy17.onError(Unknown Source)
at com.twilio.chat.internal.StatusListenerForwarder$2.run(StatusListenerForwarder.java:46)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8167)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.twilio.chat.Members.addByIdentity(java.lang.String, com.twilio.chat.StatusListener)' on a null object reference
at com.zofeur.customer.views.fragments.SupportFragment.addMemberInChannel(SupportFragment.kt:259)
at com.zofeur.customer.views.fragments.SupportFragment.access$addMemberInChannel(SupportFragment.kt:22)
at com.zofeur.customer.views.fragments.SupportFragment$joinChannel$1.onError(SupportFragment.kt:249)
I have been looking for several solutions but unable to do so.
Below is the code for my Fragment:
Support Fragment:
private fun createChannel(channelUniqueName: String) {
mViewModel.chatClient?.channels?.getChannel(channelUniqueName,
object : CallbackListener<Channel>() {
override fun onSuccess(channel: Channel?) {
if (channel != null) {
mViewModel.channel = channel
joinChannel(channel)
}
}
override fun onError(errorInfo: ErrorInfo?) {
super.onError(errorInfo)
if (errorInfo?.code == Constants.ERROR_CHANNEL_NOT_FOUND) {
mViewModel.chatClient?.channels?.channelBuilder()
?.withUniqueName(channelUniqueName)
?.withType(Channel.ChannelType.PRIVATE)
?.build(object : CallbackListener<Channel>() {
override fun onSuccess(channel: Channel?) {
requireContext().T("Channel Created $channel")
if (channel != null) {
mViewModel.channel = channel
joinChannel(channel)
}
}
})
} else {
requireContext().T("Channel not created" + errorInfo.toString())
}
}
})
}
private fun joinChannel(channel: Channel) {
channel.join(object : StatusListener() {
override fun onSuccess() {
requireContext().T("Channel Joined" + channel.uniqueName)
addMemberInChannel(channel, identity)
}
override fun onError(errorInfo: ErrorInfo) {
if (errorInfo.code == Constants.ERROR_MEMBER_ALREADY_EXISTS) {
// already join member
addMemberInChannel(channel, identity)
} else {
requireContext().T("Error joining channel$errorInfo")
}
}
})
}
private fun addMemberInChannel(channel: Channel, identity: String) {
if (mViewModel.channel.createdBy == mViewModel.chatClient.myIdentity) {
channel.members.addByIdentity(identity, object : StatusListener() {
override fun onSuccess() {
requireContext().T("Member added successfully" + channel.uniqueName)
}
override fun onError(errorInfo: ErrorInfo?) {
super.onError(errorInfo)
requireContext().T("Channel member added error" + errorInfo.toString())
}
})
} else {
requireContext().T("You cannot add member, You don't have rights.")
}
}
Any sort of help would be very helpful. Thanks in advance.
Hi I was facing the same issue When I debugged a deep longer I found out that when you create a channel it has 3 States:
SynchronizationStatus_STARTED
SynchronizationStatus_CHANNELS_COMPLETED
SyncronizationStatus_COMPLETED
You need to perform any channel related operation after the client SyncronizationStatus_COMPLETED Hope it works thanks just like that
client.addListener(object :ChatClientListener{
override fun onClientSynchronization(p0:
ChatClient.SynchronizationStatus?) {
if (p0 == ChatClient.SynchronizationStatus.COMPLETED) {
// Client is now ready for business, start working
mViewModel.chatClient = client
}
}
}

Getting HTML code from website to setText on EditText

I have had many errors and while searching around I have received many different solutions that confused me and thus I man making this post to search for one final answer. So as the title states, I am trying to make my app get the HTML code of the website link that I feed it and will then sniff out information from that to set into my EditText. I have tried searching around, and a solution I received and changed a little was to use this Utility class
import androidx.appcompat.app.AppCompatActivity
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.MalformedURLException
import java.net.URL
object ContentScrapper {
fun getHTMLData(activity: AppCompatActivity,url: String, scrapListener: ScrapListener) {
Thread(Runnable {
val google: URL?
val `in`: BufferedReader?
var input: String?
val stringBuffer = StringBuffer()
try {
google = URL(url)
`in` = BufferedReader(InputStreamReader(google.openStream()))
while (true) {
if (`in`.readLine().also { input = it } == null)
break
stringBuffer.append(input)
}
`in`.close()
activity.runOnUiThread {
scrapListener.onResponse(stringBuffer.toString())
}
} catch (e: MalformedURLException) {
e.printStackTrace()
activity.runOnUiThread {
scrapListener.onResponse(null)
}
}
}).start()
}
interface ScrapListener {
fun onResponse(html: String?)
}
}
Like this in my Main Activity
ContentScrapper.getHTMLData(this,"http://google.com/",object : ContentScrapper.ScrapListener{
override fun onResponse(html: String?) {
if(html != null) {
editTexttest.setText(html)
} else {
Toast.makeText(this#SplashActivity,"Not found",Toast.LENGTH_LONG).show()
}
}
})
And I did, but initialising the EditText like this so seemed to return a null error
val testingbox: EditText = findViewById(R.id.editTexttest)
So I looked around and found that I didn't need to initialise and I could just do editTexttest.setText?
But then I received these errors
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.EditText.setText(java.lang.CharSequence)' on a null object reference
at com.example.myapplication.MainActivity$onCreate$1.onResponse(MainActivity.kt:41)
at com.example.myapplication.ContentScrapper$getHTMLData$1$2.run(Util.kt:31)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Line 41 was the editTexttest.setText and line 31 was scrapListener.onResponse(stringBuffer.toString()).
If anyone could explain what is wrong that would be great. Thanks.
EDIT: I tunnel visioned and was looking at the wrong activity the entire time. Dumb mistake on my part.

FATAL EXCEPTION : NoSuchMethodError: No virtual method inset(IIII)Landroid/view/WindowInsets

In my app I use this method to detect the keyboard on screen. It works perfectly on api 28+ But once I go below api 28 it starts to cause crashes.
private fun isKeyboardOpen() {
window?.decorView?.setOnApplyWindowInsetsListener { v, insets ->
val systemWindowInsets = insets.inset(0,0,0,200)
imeVisible = ViewCompat.getRootWindowInsets(requireView())?.getInsets(ime())
if(imeVisible != null){
if(imeVisible?.bottom!! > 0){
ivWeatherIcon1.visibility = View.INVISIBLE
} else {
ivWeatherIcon1.visibility = View.VISIBLE
}
}
systemWindowInsets
}
}
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app, PID: 8062
java.lang.NoSuchMethodError: No virtual method inset(IIII)Landroid/view/WindowInsets; in class Landroid/view/WindowInsets; or its super classes (declaration of 'android.view.WindowInsets' appears in /system/framework/framework.jar!classes2.dex)
at com.app.framework.presentation.workouts.reframe.Workout$isKeyboardOpen$1.onApplyWindowInsets(WorkoutMoodReframe.kt:881)
at android.view.View.dispatchApplyWindowInsets(View.java:9225)
at android.view.ViewGroup.dispatchApplyWindowInsets(ViewGroup.java:6929)
at android.view.ViewRootImpl.dispatchApplyInsets(ViewRootImpl.java:1568)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1812)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
at android.view.Choreographer.doCallbacks(Choreographer.java:723)
at android.view.Choreographer.doFrame(Choreographer.java:658)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6494)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
Is there a way to make this method work back to api 23?
Obviously, keyboard appearance support does not support api <28 yet, so until backward compatibility for getInsets (ime ()) is released - you can use the following code:
private fun isKeyboardOpen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// your code above
} else {
// code from source below
}
}
How to check visibility of software keyboard in Android?

Categories

Resources