Loading an image into a RecyclerView cell - kotlin

override fun onBindViewHolder(holder: CustomViewHolder, position: Int) {
val itunesStoreItemTitle = itunes.results.get(position)
val imageURL = itunesStoreItemTitle.artworkUrl100
//val inputStream = URL(imageURL).openStream()
//val posterImage = BitmapFactory.decodeStream(inputStream)
holder?.view?.textView_iTunes_title?.text = itunesStoreItemTitle.collectionName
//holder?.view?.imageView_itunes?.setImageBitmap(posterImage)
holder?.view?.textView_iTunes_Description?.text = itunesStoreItemTitle.longDescription
}
from my MainActivity class
fun fetchJSON() {
println("Attempting to fetch JSON")
val url = URL(BASE_URL).addParameters(iTunesMap)
val request = Request.Builder().url(url).build()
val client = OkHttpClient()
client.newCall(request).enqueue(object: Callback {
override fun onResponse(call: Call, response: Response) {
val body = response?.body?.string()
val gson = GsonBuilder().create()
val iTunesFeed = gson.fromJson(body, iTunesFeed::class.java)
runOnUiThread {
recyclerView_main.adapter = MoshiAdapter(iTunesFeed)
}
println(body)
}
override fun onFailure(call: Call, e: IOException) {
println("Failed to fetch data")
}
})
}
I am trying to load images into my RecyclerView cell but it crashes on the first commented line.
CRASH LOG
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.oneorangetree.itunessearch, PID: 17091
android.os.NetworkOnMainThreadException
at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1605)
at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:115)
at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:103)
at java.net.InetAddress.getAllByName(InetAddress.java:1152)
at com.android.okhttp.Dns$1.lookup(Dns.java:41)
at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:178)
at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:144)
at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:86)
at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:176)
at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:128)
at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:97)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:289)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:232)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:465)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:411)
at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:248)
at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getInputStream(DelegatingHttpsURLConnection.java:211)
at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:30)
at java.net.URL.openStream(URL.java:1072)
at com.oneorangetree.itunessearch.adapters.MoshiAdapter.onBindViewHolder(MoshiAdapter.kt:30)
at com.oneorangetree.itunessearch.adapters.MoshiAdapter.onBindViewHolder(MoshiAdapter.kt:14)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:22844)
at android.view.ViewGroup.layout(ViewGroup.java:6389)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1843)
at android.view.View.layout(View.java:22844)
at android.view.ViewGroup.layout(ViewGroup.java:6389)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:22844)
at android.view.ViewGroup.layout(ViewGroup.java:6389)
at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
at android.view.View.layout(View.java:22844)
at android.view.ViewGroup.layout(ViewGroup.java:6389)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
E/AndroidRuntime: at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:22844)
at android.view.ViewGroup.layout(ViewGroup.java:6389)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:22844)
at android.view.ViewGroup.layout(ViewGroup.java:6389)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:784)
at android.view.View.layout(View.java:22844)
at android.view.ViewGroup.layout(ViewGroup.java:6389)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3470)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2938)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1952)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8171)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:972)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:731)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
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)

your issue is very clear, android.os.NetworkOnMainThreadException occurs when you try to access network on your main thread, please use Rx or AsyncTask to handle network request, refer RxAndroid

Related

Kotlin: I have a problem while switching from one Activity to another?

I have a problem when I want to switch between two activities.
This is my code on the first activity. I want to switch to the CatDoorActivity.
modifier = Modifier.clickable {
val intent = Intent(this, CatDoorActivity::class.java)
intent.putExtra("UUID", deviceUUID).putExtra("TITLE", deviceTitle)
this.startActivity(intent)
}
My Problem is this exception after running that code:
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.mycatbellproject/com.example.mycatbellproject.CatDoorActivity}; have you declared this activity in your AndroidManifest.xml?
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:2065)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1727)
at android.app.Activity.startActivityForResult(Activity.java:5314)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:705)
at android.app.Activity.startActivityForResult(Activity.java:5272)
at androidx.activity.ComponentActivity.startActivityForResult(ComponentActivity.java:686)
at android.app.Activity.startActivity(Activity.java:5658)
at android.app.Activity.startActivity(Activity.java:5611)
at com.example.mycatbellproject.MainActivity$CardItem$1.invoke(MainActivity.kt:255)
at com.example.mycatbellproject.MainActivity$CardItem$1.invoke(MainActivity.kt:254)
at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$2.invoke-k-4lQ0M(Clickable.kt:153)
at androidx.compose.foundation.ClickableKt$clickable$4$gesture$1$2.invoke(Clickable.kt:142)
at androidx.compose.foundation.gestures.TapGestureDetectorKt$detectTapAndPress$2$1$1.invokeSuspend(TapGestureDetector.kt:223)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:178)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:328)
at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter$PointerEventHandlerCoroutine.offerPointerEvent(SuspendingPointerInputFilter.kt:511)
at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.dispatchPointerEvent(SuspendingPointerInputFilter.kt:406)
at androidx.compose.ui.input.pointer.SuspendingPointerInputFilter.onPointerEvent-H0pRuoY(SuspendingPointerInputFilter.kt:419)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:310)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:297)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:297)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:297)
at androidx.compose.ui.input.pointer.Node.dispatchMainEventPass(HitPathTracker.kt:297)
at androidx.compose.ui.input.pointer.NodeParent.dispatchMainEventPass(HitPathTracker.kt:179)
at androidx.compose.ui.input.pointer.HitPathTracker.dispatchChanges(HitPathTracker.kt:98)
at androidx.compose.ui.input.pointer.PointerInputEventProcessor.process-BIzXfog(PointerInputEventProcessor.kt:80)
at androidx.compose.ui.platform.AndroidComposeView.sendMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1205)
at androidx.compose.ui.platform.AndroidComposeView.handleMotionEvent-8iAsVTc(AndroidComposeView.android.kt:1155)
at androidx.compose.ui.platform.AndroidComposeView.dispatchTouchEvent(AndroidComposeView.android.kt:1095)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3118)
E/AndroidRuntime: at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2799)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:488)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1871)
at android.app.Activity.dispatchTouchEvent(Activity.java:4125)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:446)
at android.view.View.dispatchPointerEvent(View.java:14568)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6016)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:5819)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5310)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5485)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5542)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5367)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5333)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5341)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5314)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8080)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8031)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:7992)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8203)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:220)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:183)
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)
Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [androidx.compose.runtime.BroadcastFrameClock#f19bf6c, StandaloneCoroutine{Cancelling}#fd19935, AndroidUiDispatcher#cea91ca]
I/Process: Sending signal. PID: 7109 SIG: 9
I have added the activity to the AndroidManifest.xml:
<activity
android:name=".CatDoorActivity"
android:configChanges="orientation"
android:exported="false"
android:theme="#style/Theme.MyCatbellProject"/>
The bottom of the exception says something about coroutines. I use them in for my room database. Do I get a problem intending a new activity and switching to it while using coroutines in my room database in the first activity? I use the room database viewmodel in my first activity but I dont use that on my second activity.
That is my second activity so far:
class CatDoorActivity : ComponentActivity(){
private var uuid: String = ""
private var title: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(intent.extras != null) {
uuid = intent.extras!!.get("UUID") as String
title = intent.extras!!.get("TITLE") as String
}
setContent {
MyCatbellProjectTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
MenuScreenUI()
}
}
}
}
...
The Repository of my room db uses the coroutines:
class DeviceRepository(application: Application) {
val searchResults = MutableLiveData<List<Device>>()
private var deviceDao: DeviceDao?
private val coroutineScope = CoroutineScope(Dispatchers.Main)
val allDevices: LiveData<List<Device>>?
fun insertDevice(newDevice: Device) {
coroutineScope.launch(Dispatchers.IO) {
asyncInsert(newDevice)
}
}
private suspend fun asyncInsert(device: Device) {
deviceDao?.addDevice(device)
}
fun deleteDevice(id: Int) {
coroutineScope.launch(Dispatchers.IO) {
asyncDelete(id)
}
}
private suspend fun asyncDelete(id: Int) {
deviceDao?.deleteDevice(id)
}
fun findDevice(name: String) {
coroutineScope.launch(Dispatchers.Main) {
searchResults.value = asyncFind(name).await()
}
}
private suspend fun asyncFind(name: String): Deferred<List<Device>?> =
coroutineScope.async(Dispatchers.IO) {
return#async deviceDao?.findDevice(name)
}
init {
val db: DeviceRoomDatabase? = DeviceRoomDatabase.getDatabse(application)
deviceDao = db?.deviceDao()
allDevices = deviceDao?.getAllDevices()
}
}

ClassCastException in parcel

When I try to use the ArrayList in Second_Activity, I get an error.
I can't find a solution.
I've try:
data class Site(
var site: String? = null,
var imageArray: ArrayList<Uri>? = null,
var date: String? = null
) : Parcelable {
constructor(parcel: Parcel) : this(parcel.readString(),
parcel.readArrayList(ClassLoader.getSystemClassLoader()) as ArrayList<Uri>?,
parcel.readString())
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(site)
parcel.writeArray(arrayOf(imageArray))
parcel.writeString(date)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<Site> {
override fun createFromParcel(parcel: Parcel): Site {
return Site(parcel)
}
override fun newArray(size: Int): Array<Site?> {
return arrayOfNulls(size)
}
}
}
var mArray = ArrayList<Site>()
I try to use for 'mArray[0].date'
This is the error I get:
java.lang.RuntimeException: Unable to start activity ComponentInfo{kr.ac.***.Second_Activity}:
java.lang.ClassCastException: kr.ac.***.First_Activity$Site cannot be cast to kr.ac.***.Second_Activity$Site
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2950)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3085)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1816)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6853)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:860)
I'm just not exactly sure how to read / write the ArrayList when parceling.
How can I use ArrayList in Second_Activity?
Thanks.

How to start receiver, getting "lateinit property notificationManager has not been initialized"

I am trying to make an alarm that sends notification when application is closed. I created an Alarm Manager in the MainActivity and created an inner class for the BroadcastReceiver as soon as the onReceive() is triggered, I need to send a notification. The alarm works but each time it tries to send the notification, I get an error of
2020-03-25 13:19:33.166 15045-15045/com.kotlin.ambulantlcs
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.kotlin.ambulantlcs, PID: 15045
java.lang.RuntimeException: Unable to start receiver com.kotlin.ambulantlcs.ui.MainActivity$Receiver:
kotlin.UninitializedPropertyAccessException: lateinit property
notificationManager has not been initialized
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3997)
at android.app.ActivityThread.access$1500(ActivityThread.java:267)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1992)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7777)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
Caused by: kotlin.UninitializedPropertyAccessException: lateinit property notificationManager has not been initialized
at com.kotlin.ambulantlcs.ui.MainActivity$Receiver.onReceive(MainActivity.kt:100)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3988)
at android.app.ActivityThread.access$1500(ActivityThread.java:267) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1992) 
at android.os.Handler.dispatchMessage(Handler.java:107) 
at android.os.Looper.loop(Looper.java:237) 
at android.app.ActivityThread.main(ActivityThread.java:7777) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1047)
See my whole code below:
import android.app.*
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.RemoteViews
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.NavOptions
import androidx.navigation.Navigation
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI
import com.kotlin.ambulantlcs.R
import com.kotlin.ambulantlcs.storage.SharedDataManager
import com.kotlin.ambulantlcs.ui.fragments.LoginFragmentDirections
import java.util.*
open class MainActivity : AppCompatActivity() {
lateinit var context: Context
lateinit var alarmManager: AlarmManager
val obj: MainActivity = this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val appBarConfiguration = AppBarConfiguration
.Builder(R.id.homeFragment, R.id.loginFragment)
.build()
setAlarm()
if(SharedDataManager.getInstance(this).isLoggedIn) {
var navOptions = NavOptions.Builder()
.setPopUpTo(R.id.action_login_Home, true)
.build()
val navController = Navigation.findNavController(this, R.id.fragment)
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)
navController.navigate(
LoginFragmentDirections.actionLoginHome()
)
} else {
val navController = Navigation.findNavController(this, R.id.fragment )
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration)
}
}
override fun onBackPressed() {
Toast.makeText(applicationContext, "Function is not allowed", Toast.LENGTH_SHORT).show()
}
override fun onSupportNavigateUp(): Boolean {
return NavigationUI.navigateUp(Navigation.findNavController(this, R.id.fragment), null)
}
fun setAlarm() {
Log.d("MainActivity", "Create: ${Date().toString()}")
context = this
alarmManager = getSystemService(Context.ALARM_SERVICE) as AlarmManager
val seconds = 10 * 1000
val intent = Intent(context, Receiver::class.java)
val pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
Log.d("MainActivity", "SECONDS: ${seconds.toLong()}")
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, seconds.toLong(), seconds.toLong(), pendingIntent)
}
class Receiver : BroadcastReceiver() {
lateinit var notificationManager : NotificationManager
lateinit var notificationChannel : NotificationChannel
lateinit var builder : Notification.Builder
private val channelId = "i.apps.notifications"
private val description = "Test notification"
override fun onReceive(context: Context?, intent: Intent?) {
Log.d("MainActivity", " Receiver: ${Date().toString()}")
val intent = Intent(context, MainActivity::class.java)
val pIntent = PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
val contentView = RemoteViews("com.kotlin.ambulantlcs",
R.layout.activity_main)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
notificationChannel = NotificationChannel(
channelId,description,NotificationManager.IMPORTANCE_HIGH)
notificationChannel.enableLights(true)
notificationChannel.lightColor = Color.GREEN
notificationChannel.enableVibration(false)
notificationManager.createNotificationChannel(notificationChannel)
builder = Notification.Builder(context, channelId)
.setContent(contentView)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pIntent)
}else{
builder = Notification.Builder(context)
.setContent(contentView)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentIntent(pIntent)
}
notificationManager.notify(1234,builder.build())
}
}
}
How can I correct this?
Your notificationManger is null (you dont initialize him). Try this:
if (notificationManager == null) {
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
The reason the app crashes is that you don't initialize notificationManager. Instead of declaring it as lateinit var you could just initialize it in your Receiver class:
val notificationManager : NotificationManager = getSystemService(Context.NOTIFICATION_SERVICE)

Kotlin null pointer exception when trying to get context from Registar in Flutter

I'm trying to create a Flutter Plugin that uses a native Android sdk
I'm able to compile the .aar libraries of the sdk and use them in the project but the sdk requires me to get the context of the main activity
here is the error im getting
E/MethodChannel#mychart_plugin(16277): Failed to handle method call
E/MethodChannel#mychart_plugin(16277): kotlin.KotlinNullPointerException
E/MethodChannel#mychart_plugin(16277): at org.ccf.flutter.plugin.mychart_plugin.MychartPlugin.getContext(MychartPlugin.kt:79)
E/MethodChannel#mychart_plugin(16277): at epic.mychart.android.library.api.authentication.WPAPIAuthentication$1.getContext(WPAPIAuthentication.java:564)
E/MethodChannel#mychart_plugin(16277): at epic.mychart.android.library.prelogin.AuthenticationService.libraryLogin(AuthenticationService.java:461)
E/MethodChannel#mychart_plugin(16277): at epic.mychart.android.library.api.authentication.WPAPIAuthentication.login(WPAPIAuthentication.java:411)
E/MethodChannel#mychart_plugin(16277): at org.ccf.flutter.plugin.mychart_plugin.MychartPlugin.onMethodCall(MychartPlugin.kt:42)
E/MethodChannel#mychart_plugin(16277): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:201)
E/MethodChannel#mychart_plugin(16277): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:88)
E/MethodChannel#mychart_plugin(16277): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:219)
E/MethodChannel#mychart_plugin(16277): at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#mychart_plugin(16277): at android.os.MessageQueue.next(MessageQueue.java:325)
E/MethodChannel#mychart_plugin(16277): at android.os.Looper.loop(Looper.java:142)
E/MethodChannel#mychart_plugin(16277): at android.app.ActivityThread.main(ActivityThread.java:6541)
E/MethodChannel#mychart_plugin(16277): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#mychart_plugin(16277): at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
E/MethodChannel#mychart_plugin(16277): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
here is my code for getting the context
class MychartPlugin: MethodCallHandler, WPAPIAuthentication.IWPOnLoginListener {
private var registrar: PluginRegistry.Registrar? = null
private val LOGIN_REQUEST_CODE = 9876
fun MychartPlugin(registrar: PluginRegistry.Registrar) {
this.registrar = registrar
}
companion object {
#JvmStatic
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "mychart_plugin")
channel.setMethodCallHandler(MychartPlugin())
}
}
override fun onMethodCall(call: MethodCall, result: Result) {
if (call.method == "getPlatformVersion") {
result.success("Android ${android.os.Build.VERSION.RELEASE}")
} else if (call.method == "MyChartSdkLogin") {
WPAPIAuthentication.login(this, "TURKJ123", "TurkJ123", LOGIN_REQUEST_CODE)
result.success("called MyChartSdkLogin")
} else {
result.notImplemented()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
// super.onActivityResult(requestCode, resultCode, data)
if (requestCode == LOGIN_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
// login successful
Log.i("LoginFragment", "OK")
} else {
// login failed
val result = WPAPIAuthentication.getLoginResult(data)
Log.i("LoginFragment", result.toString())
val errorMessage = result.getErrorMessage(getContext())
if (!errorMessage.isEmpty()) {
Toast.makeText(getContext(), errorMessage, Toast.LENGTH_LONG).show()
}
}
}
}
override fun startActivityForResult(p0: Intent, p1: Int) {
// super.startActivityForResult(p0, p1)
}
override fun getSupportFragmentManager(): FragmentManager {
val act = registrar!!.activity() as FragmentActivity
return act.getSupportFragmentManager()
}
override fun getContext(): Context {
val cxt = registrar!!.context()
return cxt
}
}
notice the override getContext() method that im overriding from the sdk, I think this context call to the registar is where my KotlinNullPointerException is coming from
In getContext you have registrar!!. And registrar is a nullable field which you initialize to null and can only set in a method which you never call. Note that fun MychartPlugin isn't a constructor, you'd call it as e.g.
val plugin = MychartPlugin()
plugin.MychartPlugin(registrar)
But it doesn't seem like there is any reason to make registrar nullable or mutable in the first place. You can change to
class MychartPlugin(private val registrar: Registrar): ...
and
fun registerWith(registrar: Registrar) {
val channel = MethodChannel(registrar.messenger(), "mychart_plugin")
channel.setMethodCallHandler(MychartPlugin(registrar))
}

okhttp3: websocket - java.io.EOFException: null - okio.RealBufferedSource.require(RealBufferedSource.java:61)

In my build.gradle:
"com.squareup.okhttp3:okhttp:3.13.1",
'com.squareup.okhttp3:logging-interceptor:3.13.1',
Kotlin project open connect to websocket:
const val WEB_SOCKET_URL = "wss://api.lbkex.com/ws/V2/";
fun main(args: Array<String>) {
val оkHttpClient = OkHttpClient()
val wsListener = object : WebSocketListener() {
override fun onOpen(ws: WebSocket, response: Response) {
super.onOpen(ws, response)
val requestJson = """{"action": "subscribe", "subscribe": "tick", "pair": "vtho_eth"}"""
ws.send(requestJson)
}
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
super.onClosing(webSocket, code, reason)
logger.info("ws Closing, reason = " + reason)
}
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
super.onClosed(webSocket, code, reason)
logger.info("ws Closed")
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
super.onFailure(webSocket, t, response)
logger.error("ws Failure ", t)
}
override fun onMessage(webSocket: WebSocket, text: String) {
super.onMessage(webSocket, text)
logger.info("ws Text message: $text")
}
override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
super.onMessage(webSocket, bytes)
}
}
logger.info("Started")
val wsRequest = Request.Builder()
.url(WEB_SOCKET_URL)
.build()
val ws = оkHttpClient.newWebSocket(wsRequest, wsListener)
}
As result I success open webscocket to wss://api.lbkex.com/ws/V2/.
As result method onMessage is call many times. Nice.
But after 15 minutes call method onFailure with error:
13:40:16.687 [OkHttp https://api.lbkex.com/...] ERROR MAIN_LOGGER - ws Failure
java.io.EOFException: null
at okio.RealBufferedSource.require(RealBufferedSource.java:61)
at okio.RealBufferedSource.readByte(RealBufferedSource.java:74)
at okhttp3.internal.ws.WebSocketReader.readHeader(WebSocketReader.java:117)
at okhttp3.internal.ws.WebSocketReader.processNextFrame(WebSocketReader.java:101)
at okhttp3.internal.ws.RealWebSocket.loopReader(RealWebSocket.java:274)
at okhttp3.internal.ws.RealWebSocket$2.onResponse(RealWebSocket.java:214)
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206)
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)