Mahmoud Nabil
Mahmoud Nabil

Reputation: 371

Why get host name as string resource gives me NullPointerException?

When starting the application, I was trying to create preferences and edit its values. The getDefaultHostName() method threw a Null Pointer Exception. Below, there is a code sample, if anyone can help.

Thank you..

val pref = PreferenceManager.getDefaultSharedPreferences(this)
        if (TextUtils.isEmpty(pref.getString(Utils.PREFS_HOST_NAME, null))) {
            // No preferences found. Save default values.
            val editor = pref.edit()
            editor.putString(Utils.PREFS_HOST_NAME, getDefaultHostName())
            editor.putBoolean(Utils.PREFS_USE_TLS, getDefaultTLS())
            editor.apply()
        }
private val sContext: MyApp? = null
fun getDefaultHostName(): String {
        return sContext!!.resources
            .getString(if (isEmulator()) R.string.emulator_host_name else R.string.default_host_name)
    }
<string name="default_host_name">Default host name</string>

Application class extends DefaultLifecycleObserver

class MyApp : Application(), DefaultLifecycleObserver {

    lateinit var userPreferences: UserPreferencesRepository
    private val sContext: MyApp? = null

    private var sContactsObserver: ContentObserver? = null

    // The Tinode cache is linked from here so it's never garbage collected.
    private val sCache: Cache? = null

    private var sVideoCache: SimpleCache? = null

    private var sAppVersion: String? = null
    private var sAppBuild = 0

    companion object {
        var simpleCache: SimpleCache? = null
        private val TAG: String =
            GLOBAL_TAG + " " + MyApp::class.java.simpleName

        @get:Synchronized
        lateinit var instance: MyApp private set
        /*Vid*/
        // 256 MB.
        private val PICASSO_CACHE_SIZE: Int = 1024 * 1024 * 256
        private val VIDEO_CACHE_SIZE = 1024 * 1024 * 256

        private var sContactsObserver: ContentObserver? = null

        // The Tinode cache is linked from here so it's never garbage collected.
        private var sCache: Cache? = null

        private var sVideoCache: SimpleCache? = null
    }
}
override fun onCreate() {
        super<Application>.onCreate()
        instance = this
        try {
            val pi = packageManager.getPackageInfo(packageName, 0)
            instance.sAppVersion = pi.versionName
            if (TextUtils.isEmpty(instance.sAppVersion)) {
                instance.sAppVersion = BuildConfig.VERSION_NAME
            }
            instance.sAppBuild = pi.versionCode
            if (instance.sAppBuild <= 0) {
                instance.sAppBuild = BuildConfig.VERSION_CODE
            }
        } catch (e: PackageManager.NameNotFoundException) {
            Log.w(MyApp.TAG, "Failed to retrieve app version", e)
        }
        FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG)
        val br: BroadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                val token = intent.getStringExtra("token")
                if (token != null && token != "") {
                    Cache.tinode!!.setDeviceToken(token)
                }
            }
        }
        val lbm = LocalBroadcastManager.getInstance(this)
        lbm.registerReceiver(br, IntentFilter("FCM_REFRESH_TOKEN"))
        lbm.registerReceiver(
            HangUpBroadcastReceiver(),
            IntentFilter(Const.INTENT_ACTION_CALL_CLOSE)
        )
        createNotificationChannels()
        ProcessLifecycleOwner.get().lifecycle.addObserver(this)

        val pref = PreferenceManager.getDefaultSharedPreferences(this)
        if (TextUtils.isEmpty(pref.getString(Utils.PREFS_HOST_NAME, null))) {
            val editor = pref.edit()
            editor.putString(Utils.PREFS_HOST_NAME, getDefaultHostName())
            editor.putBoolean(Utils.PREFS_USE_TLS, getDefaultTLS())
            editor.apply()
        }
        WorkManager.getInstance(this).pruneWork()

        val client: OkHttpClient = OkHttpClient.Builder()
            .cache(
                okhttp3.Cache(
                    createDefaultCacheDir(this)!!,
                    MyApp.PICASSO_CACHE_SIZE.toLong()
                )
            )
            .addInterceptor(Interceptor { chain: Interceptor.Chain ->
                val tinode: Tinode = Cache.tinode!!
                val picassoReq = chain.request()
                val headers: Map<String?, String?>
                if (tinode.isTrustedURL(picassoReq.url.toUrl())) {
                    headers = tinode.requestHeaders
                    var builder: okhttp3.Request.Builder = picassoReq.newBuilder()
                    for ((key, value) in headers) {
                        builder = builder.addHeader(key, value)
                    }
                    return@Interceptor chain.proceed(builder.build())
                } else {
                    return@Interceptor chain.proceed(picassoReq)
                }
            })
            .build()
        Picasso.setSingletonInstance(Picasso.Builder(this)
            .requestTransformer { request: Request ->
                if (request.uri != null && Tinode.isUrlRelative(request.uri.toString())) {
                    val url: URL = Cache.tinode!!.toAbsoluteURL(request.uri.toString())!!
                    if (url != null) {
                        return@requestTransformer request.buildUpon()
                            .setUri(Uri.parse(url.toString())).build()
                    }
                }
                request
            }
            .downloader(OkHttp3Downloader(client))
            .build())

        val cm = getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
            ?: return
        val req =
            NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                .build()
        cm.registerNetworkCallback(req, object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                super.onAvailable(network)
                if (!TextUtils.isEmpty(BaseDb.instance!!.uid)) {
                    // Connect right away if UID is available.
                    Cache.tinode!!.reconnectNow(true, false, false)
                }
            }
        })
    }

get context method

fun getAppContext(): Context? {
        return sContext
    }

Process: com.elto.date, PID: 31344 java.lang.RuntimeException: Unable to create application com.elto.date.lightDark.MyApp: java.lang.NullPointerException at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7109) at android.app.ActivityThread.access$1600(ActivityThread.java:271) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2134) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:210) at android.os.Looper.loop(Looper.java:299) at android.app.ActivityThread.main(ActivityThread.java:8319) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038) Caused by: java.lang.NullPointerException at com.elto.date.lightDark.MyApp.getDefaultHostName(MyApp.kt:240) at com.elto.date.lightDark.MyApp.onCreate(MyApp.kt:141) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1212) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7103) at android.app.ActivityThread.access$1600(ActivityThread.java:271)  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2134)  at android.os.Handler.dispatchMessage(Handler.java:106)  at android.os.Looper.loopOnce(Looper.java:210)  at android.os.Looper.loop(Looper.java:299)  at android.app.ActivityThread.main(ActivityThread.java:8319)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1038) 

Upvotes: 1

Views: 139

Answers (1)

Egor
Egor

Reputation: 40218

Why get host name as string resource gives me NullPointerException?

From what I can tell, nothing in your code ever initializes the sContext property. Hence, when sContext!! is executed inside getDefaultHostName(), a NullPointerException is thrown. To fix it, you should initialize sContext, likely inside MyApp.onCreate().

Upvotes: 0

Related Questions