0

I have a android app i need to save value in sharedpreferences in android using kotlin. sample code below.

my value is : AppdatabaseIMP@43b8de6 ------- its a Appdatabase type so i convert to string like this val APPDBSTR = appDatabase.toString()

save:

val pref = cc.getApplicationContext().getSharedPreferences("MyPrefdd", 0)
val editor = pref.edit()
editor.putString("APPDBSTR", APPDBSTR)
editor.apply()

get:

val pref = context!!.getSharedPreferences("MyPrefdd", 0)
val mFragAPPDBSTR = pref.getString("APPDBSTR", null)

here i can get the value wihout problem, but i want re convert my string to previus type how to do that in kotlin

UPDATE :

companion object {
        /**
         * new instance pattern for fragment
         */
        @JvmStatic
        fun newInstance(myObject: List<TransactionEntity>?, cc: Context, appDatabase: AppDatabase, networkDefinitionProvider: NetworkDefinitionProvider, incoming: TransactionAdapterDirection): SendingFragment {

            val gson = Gson()
            val gson1 = GsonBuilder().create()
            val model = myObject as List<TransactionEntity>
            val IT = gson.toJson(model)
            System.out.println("json representation :" + IT)

            val bo = ByteArrayOutputStream()
        val so = ObjectOutputStream(bo)
        so.writeObject(appdatabase)
        so.flush()
        val serializedObject = String(Base64.encode(bo.toByteArray()))

            val bundle = Bundle()
            bundle.putString("bundleValue", IT)
             bundle.putSerializable("serializedObject",serializedObject)
            val sendFragament: SendingFragment = SendingFragment()
            sendFragament.setArguments(bundle)
            return sendFragament
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

        val gson = Gson()
        val gson1 = GsonBuilder().create()
        val pref = context!!.getSharedPreferences("MyPrefdd", 0)
        val mFragIT = pref.getString("NEWIT", "")

         val mFragserializedObject = arguments!!.getSerializable("serializedObject") --- i here i can the value 

        }

I got this error :

Caused by: java.io.NotSerializableException: com.crypto.wallet.data.AppDatabase_Impl
                                                                   at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1344)
                                                                   at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1651)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1497)
                                                                   at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1461)
                                                                   at com.crypto.wallet.activities.SendingFragment$Companion.newInstance(SendingFragment.kt:52)
                                                                   at com.crypto.wallet.activities.MainActivity.setupViewPager(MainActivity.kt:420)
                                                                   at com.crypto.wallet.activities.MainActivity.access$setupViewPager(MainActivity.kt:70)
                                                                   at com.crypto.wallet.activities.MainActivity$onCreate$outgoingTransactionsObserver$1.onChanged(MainActivity.kt:277)
                                                                   at com.crypto.wallet.activities.MainActivity$onCreate$outgoingTransactionsObserver$1.onChanged(MainActivity.kt:70)
                                                                   at android.arch.lifecycle.LiveData.considerNotify(LiveData.java:109)
                                                                   at android.arch.lifecycle.LiveData.dispatchingValue(LiveData.java:126)
                                                                   at android.arch.lifecycle.LiveData.setValue(LiveData.java:282)
                                                                   at android.arch.lifecycle.LiveData$1.run(LiveData.java:87)
                                                                   at android.os.Handler.handleCallback(Handler.java:739)
                                                                   at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                   at android.os.Looper.loop(Looper.java:135)

How to deserialize it ?

Karthikeyan
  • 385
  • 3
  • 7
  • 18

1 Answers1

2

What you are getting there when calling toString is only a hash of the object in the memory. It does not contain the actual object values, so it can not be restored this way.

https://developer.android.com/reference/java/lang/Object.html#toString()
The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object.

You need to serialize the whole object for the restoration to work. Depending on your class, this could be as simple as extending Serializable and getting the String as described in this answer: https://stackoverflow.com/a/8887244/4193263

ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream so = new ObjectOutputStream(bo);
so.writeObject(myObject);
so.flush();
String serializedObject = new String(Base64.encodeBase64(bo.toByteArray()));
ByteHamster
  • 4,884
  • 9
  • 38
  • 53
  • @ByteHamster +1. @Karthikeyan Also, Why would you save your database to Shared Preferences ? What is `Appdatabase` class ? – Damiii Oct 13 '18 at 08:27
  • i have to perform some process and send pack to shard pref i can not access db here – Karthikeyan Oct 13 '18 at 08:33
  • @Karthikeyan I added a few lines to describe how you can serialize an object to string. Please keep in mind that a database access class with Context object or SQLiteDatabase can likely not be serialized. Why can't you directly access the database from your process? – ByteHamster Oct 13 '18 at 08:42
  • 1
    This is not a reversible way to convert a ByteArrayOutputStream to a String as written. You must use something like Base64; you cannot just use `bo.toString()`. – Louis Wasserman Oct 13 '18 at 16:31
  • @Louis Wasserman Just out of interest, do you have an example where this goes wrong? I mean, you will likely get a string with unprintable characters, but shouldn't `getBytes` reverse that? The only thing that came to my mind are null characters, but that does not seem to be a problem in Java – ByteHamster Oct 13 '18 at 22:34
  • 1
    @ByteHamster read the docs of `toString`: "This method always replaces malformed-input and unmappable-character sequences with the default replacement string for the platform's default character set." So if the wrong byte sequence happens to appear in the bytes, it gets erased. – Louis Wasserman Oct 13 '18 at 23:01
  • @ByteHamster i update my question as per your idea but it does not working well – Karthikeyan Oct 15 '18 at 05:06
  • Well, the error already says what the problem is. Your class `appdatabase` can not be serialized. This means that you can not convert the object to a String. Saving the object in shared preferences will not work. You might be able to use static variables, even though it is probably not good style either. To get static variables in Kotlin, you can use this: https://stackoverflow.com/q/40352684/4193263 – ByteHamster Oct 15 '18 at 06:11