简体   繁体   English

应用在混淆后读取共享首选项时崩溃

[英]App crashes on reading shared preferences after obfuscation

In my application, I am using SharedPreferences to store some user preferences.在我的应用程序中,我使用 SharedPreferences 来存储一些用户首选项。 The application was not obfuscated (-dontobfuscate in the proguard file).应用程序没有被混淆(proguard 文件中的 -dontobfuscate)。

Now in the next version of the application, I want to enable obfuscation.现在在应用程序的下一个版本中,我想启用混淆。 When I try this, the application returns NullPointerException while reading the SharedPreferences data from the previous version of the application.当我尝试此操作时,应用程序在从应用程序的先前版本读取 SharedPreferences 数据时返回 NullPointerException。 The error log is not helpful because the code is already obfuscated and it does not provide meaningful information.错误日志没有帮助,因为代码已经被混淆并且没有提供有意义的信息。 However, while trying in the debug mode I found the crash may be due to null context which is a static variable in the code!但是,在调试模式下尝试时,我发现崩溃可能是由于 null 上下文造成的,它是代码中的静态变量! That should not be the case because the application works file if SharedPreferences were not there already.这不应该是这种情况,因为如果 SharedPreferences 不存在,则应用程序工作文件。

Is there any way the app can still read the SharedPreferences data from unobfuscated version?应用程序是否仍然可以从未混淆版本中读取 SharedPreferences 数据?

Writing / reading the SharedPreferences is pretty standard: Writing:编写/阅读 SharedPreferences 是非常标准的:写作:

SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor prefsEditor = mPrefs.edit();
    prefsEditor.putString("userUnitsOption", "C");
    //apply the storage
    prefsEditor.apply();

Reading:阅读:

final SharedPreferences mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
        return mPrefs.getString("userUnitsOption", "A");

If you want to use shared preferences in Android then use it as given below :如果您想在 Android 中使用共享首选项,请按如下所示使用它:

First, you have to store your preferences like this :首先,您必须像这样存储您的首选项:

SharedPreferences.Editor editor = getSharedPreferences("mySharedPref", MODE_PRIVATE).edit(); 
            editor.putString("myName", "abc");
            editor.apply();

Now, To read or get those stored shared preferences write code as given below :现在,要读取或获取这些存储的共享首选项,请编写如下代码:

SharedPreferences prefs = MainActivity.this.getSharedPreferences("mySharedPref", MODE_PRIVATE); // Here  MainActivity.this represent the context. So you can use your context in place  of MainActivity.this
            String strName = prefs.getString("myName","defaultName");

In Kotlin ,在科特林

Usage :用法
private val sharedPref = defaultPrefs(this)私有 val sharedPref = defaultPrefs(this)

To Save Data--> sharedPref[KEY] = *String data to save*保存数据--> sharedPref[KEY] = *String data to save*

To Get Data --> val userDetails = sharedPref[KEY, ""]获取数据--> val userDetails = sharedPref[KEY, ""]

Create a shared preference helper class like below.创建一个共享首选项助手类,如下所示。

object PreferenceHelper {

    fun defaultPrefs(context: Context): SharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(context)

    fun customPrefs(context: Context, name: String): SharedPreferences =
        context.getSharedPreferences(name, Context.MODE_PRIVATE)

    inline fun SharedPreferences.edit(operation: (SharedPreferences.Editor) -> Unit) {
        val editor = this.edit()
        operation(editor)
        editor.apply()
    }

    /**
     * puts a key value pair in shared prefs if doesn't exists, otherwise updates value on given [key]
     */
    operator fun SharedPreferences.set(key: String, value: Any?) {
        when (value) {
            is String? -> edit { it.putString(key, value) }
            is Int -> edit { it.putInt(key, value) }
            is Boolean -> edit { it.putBoolean(key, value) }
            is Float -> edit { it.putFloat(key, value) }
            is Long -> edit { it.putLong(key, value) }
            else -> throw UnsupportedOperationException("Not yet implemented")
        }
    }

    /**
     * finds value on given key.
     * [T] is the type of value
     * @param defaultValue optional default value - will take null for strings, false for bool and -1 for numeric values if [defaultValue] is not specified
     */
    inline operator fun <reified T : Any> SharedPreferences.get(
        key: String,
        defaultValue: T? = null
    ): T? {
        return when (T::class) {
            String::class -> getString(key, defaultValue as? String) as T?
            Int::class -> getInt(key, defaultValue as? Int ?: -1) as T?
            Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T?
            Float::class -> getFloat(key, defaultValue as? Float ?: -1f) as T?
            Long::class -> getLong(key, defaultValue as? Long ?: -1) as T?
            else -> throw UnsupportedOperationException("Not yet implemented")
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM