3

Good evening everyone! I want to use shared preferences to store my token(I know that this is not secure, I am new in android development and just want to try) and then pass it to the interceptor. How can I initialize shared preferences there? Thank you! Or can you give me a tips how I can implement interceptor or store token.

Sorry, I already tried to search for this topic, and was not able to implement methods of other developers.

object NetworkModule {

    var sharedPreferences = //GET SHARED PREFERENCES THERE

    var authToken: String? = sharedPreferences.getString("Token", null)
    val baseURL = //my base url

    
    val loggingInterceptor = HttpLoggingInterceptor().apply {
        level = HttpLoggingInterceptor.Level.BODY
    }


    var httpClient = OkHttpClient.Builder().addInterceptor { chain ->
        chain.proceed(
            chain.request().newBuilder().also { it.addHeader("Authorization", "Bearer $authToken") }
                .build()
        )
    }.connectTimeout(10, TimeUnit.SECONDS)
        .writeTimeout(30, TimeUnit.SECONDS)
        .readTimeout(10, TimeUnit.SECONDS)
        .addNetworkInterceptor(loggingInterceptor)
        .build()

    val retrofit = Retrofit.Builder().baseUrl(baseURL).addConverterFactory(
        GsonConverterFactory.create()
    ).client(httpClient).build()


    val api: API by lazy { retrofit.create() }
    val apiClient = ApiClient(api)
}
GreenROBO
  • 4,725
  • 4
  • 23
  • 43

2 Answers2

1

You can access SharedPreferences anywhere from your app using ApplicationContext. It is a very common practice in Android Development and it is very safe.

To access ApplicationContext see code below:

  1. In your Application class, add an Application Singleton.

    class MyApplication : Application() {
         override fun onCreate() {
            super.onCreate()
            instance = this
         }
    
         companion object {
             lateinit var instance: MyApplication
                 private set
         }
    }
    

    (What is an Application Class?)

  2. Use ApplicationContext anywhere within your app!

    var sharedPreferences = getApplicationContext() //here you go!
    

This code does the job, however, if you are interested in Best Android development practices, please read this:

Recommended 2 Options

  1. Best Practice: Create a new Manager class that is responsible for app's entire SharedPreferences usage (ex. SharedPreferenceManager). This class is a Singleton Class that is instantiated with ApplicationContext and has all the methods related CRUD operations in SharedPreferences, in your case setToken and getToken. Since the manager class is independent, it should not cause any Lifecycle errors or NullPointer errors.

    Since attaching sample code will clutter my answer, I decided to cite someone else's code here, this will teach you how to implement it.

  2. If you are too lazy to follow #2: You can use a library that has done that for you already: Pixplicity/EasyPrefs.

    • Easy to use like Manager Class ✅
    • No more errors related to SharedPreferences
    • You could always retrofit into any existing project ✅

Let me know if you have any questions. Thanks.

minchaej
  • 1,294
  • 1
  • 7
  • 14
  • This code won't work for the singleton. You never set the variable to anything. And there's no reason to make the public property nullable, since it won't ever be null after Application is created. And it's not in a companion object. Here's a proper way to do it: https://stackoverflow.com/a/37412029/506796 – Tenfour04 Jul 13 '21 at 17:17
  • @Tenfour04 yup forgot to make it a companion object! fixed it. – minchaej Jul 13 '21 at 18:20
  • @minchaej, Thank you! I think it is what I was searching for, but I didn't understanded properly. I did this steps with the library that you gave: 1. Created class PrefsApplication with the given code(just in random place) 2. Tried to use Prefs.putString("Token","myAuthToken") In logcat: Caused by: java.lang.RuntimeException: Prefs class not correctly instantiated. Please call Builder.setContext().build() in the Application class onCreate. I think I did a mistake with PrefsApplication class. Where should I create this class(inside of Application.java???) and what to do after? Thank you!! – Andrey Arshavin Jul 13 '21 at 21:02
  • @AndreyArshavin Sure thank you for your comment. From my understanding, it sounds like you have not instantiated `Application` Class properly. Have you checked out my URL for you about `Applicaion` Class? (https://medium.com/droid-log/android-application-class-a8a1d64c82d1) – minchaej Jul 13 '21 at 23:09
0

Use these in actual implementations:

actual typealias PlatformContext = Activity  //Android

actual typealias PlatformContext = NSObject  //iOS

This is a great tutorial to achieve this and solved my problem: UserDefaults and SharedPreference in KMM

Saeed Ir
  • 1,974
  • 2
  • 20
  • 22