Mohammad Ali Shuvo
Mohammad Ali Shuvo

Reputation: 55

Java.lang.OutOfMemoryError on some specific android device

I have one app in the Play Store and which is Arabic to Bangla dictionary. I have noticed for some devices it is throwing an Java.lang.OutOfMemoryError in a function which I have given below. The app is works well on some devices but some specific devices crash due to this exception. The exception showing on the below function. My question is why this type of exception occurs and what is the possible solution for this?

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

//        realm = Realm.getDefaultInstance()
//        realm.beginTransaction()
//        realm.delete(SearchHistories::class.java)
//        realm.commitTransaction()

        if(isLoggedIn() == null) {
            if(checkNetworkConnection()) {
                val infoService: InfoService = ServiceBuilder.buildService(InfoService::class.java)
                val iRequestCall: Call<Info> = infoService.getInfo()
                iRequestCall.enqueue(object : Callback<Info> {
                    override fun onFailure(call: Call<Info>, t: Throwable) {
                        Toast.makeText(this@MainActivity, "Something went wrong", Toast.LENGTH_SHORT).show()
                    }

                    override fun onResponse(call: Call<Info>, response: Response<Info>) {
                        if(response.isSuccessful) {
                            val body = response.body()
                            realm = Realm.getDefaultInstance()
                            realm.beginTransaction()
                            val infos = Infos(
                                id = body!!.id,
                                activate_info = body.activate_info,
                                how_to_use = body.how_to_use,
                                feature = body.feature,
                                owner_info = body.owner_info,
                                contact_info = body.contact_info,
                                copyright = body.copyright,
                                created_at = body.created_at,
                                updated_at = body.updated_at
                            )
                            realm.copyToRealmOrUpdate(infos)
                            realm.commitTransaction()
                        } else {
                            Toast.makeText(this@MainActivity, "One api failure detected", Toast.LENGTH_SHORT).show()
                        }
                    }
                })
            }
        }

        mRunnable = Runnable {

            if(isLoggedIn() != null) {
                val intent = Intent(this, HomeActivity::class.java)
                startActivity(intent)
                finish()
            } else {
                val intent = Intent(this, LoginAcitvity::class.java)
                startActivity(intent)
                finish()
            }
//            Toast.makeText(this@MainActivity, "hi", Toast.LENGTH_SHORT).show()
        }

        mHandler = Handler()
        mHandler.postDelayed(mRunnable, 5000)
    }

[crash reports]

Upvotes: 0

Views: 203

Answers (1)

Some random IT boy
Some random IT boy

Reputation: 8467

For what you're explaining it could be anything: you could have a bug allocating memory or something similar to that.

What the last-line of the crash report screenshot is what gave me the final hint. BitmapFactory.nativeDecodeAsset

You're likely to be setting your images by yourself: Getting a bitmap/drawable and putting it directly to an ImageView or similar by using the setDrawable or setBitmap functions.

Inflating a Bitmap per-se is very memory expensive as a 1MB PNG on disk, when inflated, can take more than 10MB in RAM.

Get around this problem you certainly need to lower the memory consumption when loading a Bitmap, and sadly that's not a given by Android: you need to implement it yourself or use an image loading library. (Which you probably already use)

  1. If you want to implement it yourself please refer to this answer which covers the topic very extensively
  2. Use an image loading library such as Glide. It does not only provide functionality to fetch images from the internet and the http layer but you can also load drawables and svgs to your image views. It has builtin "sample-reduction" when you use the load method.
  3. You might just have lots of images in your app. Here I suggest to lazy-load them or just not loading them all. A RecyclerView with Glide can help you with that but depending on what you have you are going to require more logic

Upvotes: 1

Related Questions