From Json. as i was trying to store with Byte it gives me error - java.lang.NumberFormatException: For input string:
What number, between 0 and 255 does https://upload.wikimedia.org/wikipedia/commons/4/41/Sunflower_from_Silesia2.jpg
resolve to 0? 1? 2? .... 255? (Rhetorical) Why? (Rhetorical)
how do i store image in room database
You VERY PROBABLY SHOULD NOT but instead store the image as a file in the Apps's storage (there would be no real difference in storage space) but probably a very noticeable improvement in response times.
The value https://upload.wikimedia.org/wikipedia/commons/4/41/Sunflower_from_Silesia2.jpg
is, to many humans, obviously a link to a file that can be downloaded (an image). It does not equate to a byte or any number.
However, the file stored at that location is a series (aka stream) of bytes.
Thus in Room a ByteArray (which Room will assign a type affinity of BLOB the the column). So the column type should either be ByteArray or a type that would require a type converter where the type converter returns a ByteArray.
So instead of val image: Byte,
you would probably have val image: ByteArray,
.
To get the ByteArray you could (assuming permissions etc are all setup) use something like (but not restricted to):-
return URL(url).readBytes()
- where url, in your case, would be the String
https://upload.wikimedia.org/wikipedia/commons/4/41/Sunflower_from_Silesia2.jpg
IMPORTANT
However, at 2.7Mb

that is very likely to cause issues. Not due to SQLite limitations but due to limitations of the Android API which retrieves data from the SQLite database via a Cursor which is a buffer that is limited in size (4Mb). As such any image that is close to 4Mb may be stored but it couldn't be retrieved without complications AND highly inefficient/slow processing.
Demonstration of why NOT to store images, like the one mentioned in the question.** in the database**
As a demonstration consider the following which does store the equivalent of images (not actual images) in the image column of you table
- (i.e. ByteArrays, the content unless actually displaying the image is irrelevant Room nor SQLite knows the difference between an image and any other BLOB value)
using a slightly modified version of your ActorItem class, as :-
@Entity(tableName = "actor",indices = arrayOf(Index(value= arrayOf("id"),unique = true)))
data class ActorItem(
@PrimaryKey(autoGenerate = true)
val id_:Int,
@ColumnInfo(name = "age")
val age: String,
@ColumnInfo(name = "id")
val id: Int,
@ColumnInfo(name="image")
val image: ByteArray,
@ColumnInfo(name = "name")
val name: String
) {
@androidx.room.Dao
interface Dao {
@Insert
fun insert(actorItem: ActorItem)
}
}
- i.e. the important difference is a type of ByteArray as opposed to Byte for the image column
- for brevity/convenience the DAO class has been included (it is sufficient just to insert some columns to demonstrate why saving the image is not a very good idea)
To accompany is an @Database
class TheDatabase :-
@Database(entities = [ActorItem::class], version = 1, exportSchema = false)
abstract class TheDatabase: RoomDatabase() {
abstract fun getActorItemDao(): ActorItem.Dao
companion object {
private var instance: TheDatabase? = null
fun getInstance(context: Context): TheDatabase {
if ( instance == null) {
instance = Room.databaseBuilder(context,TheDatabase::class.java,"thedatabase.db")
.allowMainThreadQueries()
.build()
}
return instance as TheDatabase
}
}
- allowMainThreadQueries included for brevity and convenience
Finally putting the above into action via an activity is MainActivity :-
class MainActivity : AppCompatActivity() {
lateinit var db: TheDatabase
lateinit var dao: ActorItem.Dao
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
db = TheDatabase.getInstance(this)
dao = db.getActorItemDao()
val url = "https://upload.wikimedia.org/wikipedia/commons/4/41/Sunflower_from_Silesia2.jpg"
try {
for (i in 1..100) {
dao.insert(
ActorItem(
0, "The age", i,
getBitmapFromURLAsString(
url,
/* The ByteArray (bitmap) */
/* BUT for demonstration of issues associated with size issues
start at 1.08Mb size incrementing at 8kb per row
last would be 1.8Mb (100 * 8kb)
*/
i * (4096 * 2) + (1024 * 1024)),
getNameFromURLAsString(url)
)
)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
fun getBitmapFromURLAsString(url: String, size: Int): ByteArray {
/* Fake the byte array allowing the size of the bytearray to be specified */
val ba = ByteArray(size)
var byte: Byte = 8
for(i in 0 until (size)) {
ba[i] = byte++.mod(Byte.MAX_VALUE)
}
return ba
/* actual would be something like */
/* WARNING image Sunflower_from_Silesia2.jpg is 2.7Mb will likely cause issues */
//return URL(url).readBytes()
}
fun getNameFromURLAsString(url: String): String {
val split = url.split("/")
return split.get(split.size -1)
}
}
So the activity will try to insert 100 rows with a ByteArray in the image column (answer to how to store image in principle). For each row the size of the ByteArray is increased by 8k (the first row is 1.08Mb i.e. 1Mb and 8k in size). The name column
The above runs successfully without any trapped exceptions. And all 100 rows are inserted:-

using query to extract the length of each image column shows the size (of the last rows) :-

First warning sign that things are perhaps not that good
Running the query takes hardly any time at all. Refreshing, moving from start to end from the table view takes quite a bit of time (a minute (will be dependant upon PC/Laptop used)).
Second warning sign
Running the App takes a few seconds.
Third warning sign
Use i * (4096 * 2) + (1024 * 1024 * 2)),
(i.e. start at 2Mb up to 2.8Mb), run the App and try to view via App Inspection and :-

As can be seen the Rows exist and have the expected data in them :-

Try to look at the Actor table, DatabaseInspector
doesn't show the contents .
Run the query SELECT substr(image,1024 * 1024) FROM actor
(i.e. 8k for the first row 1.8k for the 100th row) WAIT (for a minute or so), scroll to the last, WAIT (for a minutes or so) and :-
