0

In debug mode, when I test with emulator device, my app works fine.

But when I upload app on google playstore and download it from market, my app is killed.

In Google play console, It says NumberFormatException Error.

Exception java.lang.NumberFormatException: s == null
  at java.lang.Integer.parseInt (Integer.java:577)
  at java.lang.Integer.parseInt (Integer.java:650)
  at com.chugnchunon.chungchunon_android.DiaryTwoActivity.onCreate$lambda-0 (DiaryTwoActivity.java:22)
  at com.google.android.gms.tasks.zzi.run (zzi.java:21)
  at android.os.Handler.handleCallback (Handler.java:938)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loopOnce (Looper.java:226)
  at android.os.Looper.loop (Looper.java:313)
  at android.app.ActivityThread.main (ActivityThread.java:8751)
  at java.lang.reflect.Method.invoke
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:571)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1135)

As It says DiaryTwoActivity, if I see the front part of that activity,

class DiaryTwoActivity : AppCompatActivity() {

    private val db = Firebase.firestore
    private val diaryDB = Firebase.firestore.collection("diary")
    private val userDB = Firebase.firestore.collection("users")

    private val userId = Firebase.auth.currentUser?.uid
    val writeTime = LocalDateTime.now().toString().substring(0, 10)
    private var from = ""
    private lateinit var remoteConfig: FirebaseRemoteConfig
    private val _mutableLiveData = MutableLiveData<AppUpdate>()

    private var diaryType = ""
    private var lastBackPressTime: Long = 0

    private val binding by lazy {
        ActivityDiaryTwoBinding.inflate(layoutInflater)
    }

    companion object {
        private var permissionCheck = false

        const val ALL_REQ_CODE: Int = 500
        const val PARTNER_REQ_CODE: Int = 600

        const val STEP_CONTACT_REQ_CODE: Int = 100
        const val STEP_REQ_CODE: Int = 200
        const val CONTACT_REQ_CODE: Int = 300
        const val IGNORING_BATTERY_OPT_REQ_CODE: Int = 400

        private var whiteCheck: Boolean = false
    }

    override fun onBackPressed() {

        val currentTime = System.currentTimeMillis()
        val interval = 2000

        if (currentTime - lastBackPressTime < interval) {
            super.onBackPressed()
            finishAffinity()
            finish()
        } else {
            lastBackPressTime = currentTime
        }
    }

    @RequiresApi(33)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        // 버전 체크
        val android_versionCode = Build.VERSION.SDK_INT
        val android_versionName = Build.VERSION.RELEASE
        val versionSet = hashMapOf(
            "android_api_level" to android_versionCode,
            "android_release_version" to android_versionName,
        )
        userDB.document("$userId")
            .set(versionSet, SetOptions.merge())

        // diaryType 받아오기 - fragment 변동
        diaryType = intent.getStringExtra("diaryType").toString()

        // 인앱업데이트
        remoteConfig = Firebase.remoteConfig
        val configSettings = remoteConfigSettings {
            minimumFetchIntervalInSeconds = 3600
        }
        remoteConfig.setConfigSettingsAsync(configSettings)

        remoteConfig.fetchAndActivate().addOnCompleteListener { task ->
            if (task.isSuccessful) {
                val gson = GsonBuilder().create()
                val result = remoteConfig.getString("app_update")
                val resultJson = gson.fromJson(result, AppUpdate::class.java)

                val currentAppVersion = packageManager.getPackageInfo(packageName, 0).versionCode

                // 현재 버전값 저장
                val currentVersionSet = hashMapOf(
                    "currentAppVersion" to currentAppVersion
                )
                userDB.document("$userId").set(currentVersionSet, SetOptions.merge())

                // 현재 버전이 remote config 버전보다 낮을 경우
                if (currentAppVersion < resultJson.app_version.toInt() && resultJson.force_update as Boolean) {


                    // 즉시 업데이트할 것
                    var window = this.window
                    window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                    window.setStatusBarColor(Color.parseColor("#B3000000"))

                    binding.updateLayout.visibility = View.VISIBLE
                    var upAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_up_enter)
                    binding.updateCardLayout.startAnimation(upAnimation)
                } else {
                    // 현재 버전이 remote config 버전보다 낮지 않을 경우
                    binding.updateLayout.visibility = View.GONE
                }

            } else {
                // remote config에서 버전을 가져오지 못한 경우
            }
        }


        // 인앱업데이트 취소 클릭
        binding.updateCancelBox.setOnClickListener {
            var downAnimation = AnimationUtils.loadAnimation(this, R.anim.slide_down_enter)
            binding.updateCardLayout.startAnimation(downAnimation)

            Handler().postDelayed({
                binding.updateLayout.visibility = View.GONE

                var window = this.window
                window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
                window.setStatusBarColor(Color.WHITE);
            }, 500)
        }

        // 인앱업데이트 확인 클릭
        binding.updateConfirmBox.setOnClickListener {
            val uri =
                "https://play.google.com/store/apps/details?id=com.chugnchunon.chungchunon_android"
            val goUpdateIntent = Intent(Intent.ACTION_VIEW, Uri.parse(uri))
            startActivity(goUpdateIntent)
        }

        // 댓글 푸시 노티피케이션 구독
        val userIdFormat = userId!!.replace(":", "")
        val firebaseMessaging = FirebaseMessaging.getInstance()
        firebaseMessaging.subscribeToTopic("$userIdFormat")

        // FCM 토큰 저장
        userDB.document("$userId")
            .get()
            .addOnSuccessListener { document ->
                try {
                    // 발급 받은 토큰이 이미 있는 경우
                    val myFcmToken = document.data?.getValue("fcmToken").toString()

                } catch (e: Exception) {
                    // 발급 받은 토큰이 없는 경우

                    FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
                        if (!task.isSuccessful) {
                            return@OnCompleteListener
                        }

                        // 발급후 토큰 저장
                        val fcmToken = task.result
                        val fcmTokenSet = hashMapOf(
                            "fcmToken" to fcmToken
                        )
                        userDB.document("$userId")
                            .set(fcmTokenSet, SetOptions.merge())
                    })
                }
            }


        // 권한 체크
        val readContactPermissionCheck =
            ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
        val stepPermissionCheck =
            ContextCompat.checkSelfPermission(this, Manifest.permission.ACTIVITY_RECOGNITION)
        val readGalleryPermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        val postNotificationPermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)

        if (Build.VERSION.SDK_INT >= 33) {
            permissionCheck = readContactPermissionCheck == PackageManager.PERMISSION_GRANTED
                    && stepPermissionCheck == PackageManager.PERMISSION_GRANTED
                    && readGalleryPermission == PackageManager.PERMISSION_GRANTED
                    && postNotificationPermission == PackageManager.PERMISSION_GRANTED
        } else {
            permissionCheck = readContactPermissionCheck == PackageManager.PERMISSION_GRANTED
                    && stepPermissionCheck == PackageManager.PERMISSION_GRANTED
                    && readGalleryPermission == PackageManager.PERMISSION_GRANTED
        }

        // 파트너 구분 x
        if (!permissionCheck) {
            binding.authNotificationLayout.visibility = View.VISIBLE
        } else {
            // 모두 허용된 경우
            binding.authNotificationLayout.visibility = View.GONE

            // 배터리 제한 없음 설정 안 한 경우
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

                val powerManager =
                    this.getSystemService(Context.POWER_SERVICE) as PowerManager
                if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
                    val intent = Intent().apply {
                        action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
                        data = Uri.parse("package:$packageName")
                        flags = Intent.FLAG_ACTIVITY_NEW_TASK
                    }
                    this.startActivity(intent)
                } else {
                    // 배터리 사용량 제한없음 권한 부여 o
                    val batteryAuthSet = hashMapOf(
                        "auth_ignoring_battery" to true,
                    )
                    userDB.document("$userId").set(batteryAuthSet, SetOptions.merge())
                }
            }

            // db에 권한 저장
            var authSet = hashMapOf(
                "auth_step" to true,
                "auth_contact" to true,
                "auth_gallery" to true,
                "auth_notification" to true,
            )
            userDB.document("$userId").set(authSet, SetOptions.merge())

            // 걸음수 호출
            val startService = Intent(this, MyService::class.java)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                ContextCompat.startForegroundService(this, startService);
            } else {
                startService(startService);
            }

            val stepAuthIntent = Intent(this, MyDiaryFragment::class.java)
            stepAuthIntent.setAction("STEP_AUTH_UPDATE")
            stepAuthIntent.putExtra("StepAuth", true)
            LocalBroadcastManager.getInstance(this).sendBroadcast(stepAuthIntent)
        }

There's only one line related to Int() is below:

remoteConfig.fetchAndActivate().addOnCompleteListener { task ->
    if (task.isSuccessful) {
        val gson = GsonBuilder().create()
        val result = remoteConfig.getString("app_update")
        val resultJson = gson.fromJson(result, AppUpdate::class.java)

        val currentAppVersion = packageManager.getPackageInfo(packageName, 0).versionCode

        // 현재 버전값 저장
        val currentVersionSet = hashMapOf(
            "currentAppVersion" to currentAppVersion
        )
        userDB.document("$userId").set(currentVersionSet, SetOptions.merge())

        // 현재 버전이 remote config 버전보다 낮을 경우
        if (currentAppVersion < resultJson.app_version.toInt() && resultJson.force_update as Boolean) {

Here, I get data from remote config of firebase and change it to toInt().

But when I print it on debug, it prints "46" well as string and it should be converted to Int.

And since it gets data well from remote config, it shouldn't be null.

Moreover, it worked well before, the only thing that I changed is I change compileSDK from 32 to 33, and minSDKVersion from 31 to 26. (my targetSDK is 31)

I'm not sure this is related to version update.

And even not sure this line causes NumberFormatException, or other part is causing issue or not.

It worked well on debug, so I can't test with emulator..

Can you see the code and give me some advice?

22 line of DiaryTwoActivity was

import androidx.lifecycle.MutableLiveData

But since I didn't use MutableLiveData in this activity, I deleted that line but still issue comes after submitting app on market.

Hyejung
  • 902
  • 1
  • 8
  • 22

0 Answers0