| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.weex; |
| |
| import static android.content.Context.MODE_PRIVATE; |
| |
| import android.annotation.SuppressLint; |
| import android.app.Application; |
| import android.content.Context; |
| import android.content.SharedPreferences; |
| import android.content.pm.ApplicationInfo; |
| import android.content.pm.PackageInfo; |
| import android.content.pm.PackageManager; |
| import android.graphics.Typeface; |
| import android.os.Build; |
| import android.os.Environment; |
| import android.support.annotation.RestrictTo; |
| import android.support.annotation.RestrictTo.Scope; |
| import android.telephony.TelephonyManager; |
| import android.text.TextUtils; |
| import android.system.Os; |
| import dalvik.system.PathClassLoader; |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileDescriptor; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.HashMap; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.concurrent.ConcurrentHashMap; |
| import org.apache.weex.common.WXConfig; |
| import org.apache.weex.utils.FontDO; |
| import org.apache.weex.utils.LogLevel; |
| import org.apache.weex.utils.TypefaceUtil; |
| import org.apache.weex.utils.WXFileUtils; |
| import org.apache.weex.utils.WXLogUtils; |
| import org.apache.weex.utils.WXSoInstallMgrSdk; |
| import org.apache.weex.utils.WXUtils; |
| import org.apache.weex.utils.WXViewUtils; |
| |
| public class WXEnvironment { |
| |
| public static final String OS = "android"; |
| public static String SYS_VERSION = android.os.Build.VERSION.RELEASE; |
| static{ |
| if(SYS_VERSION != null && SYS_VERSION.toUpperCase(Locale.ROOT).equals("P")){ |
| SYS_VERSION = "9.0.0"; |
| } |
| if(SYS_VERSION != null && SYS_VERSION.toUpperCase(Locale.ROOT).equals("Q")){ |
| SYS_VERSION = "10.0.0"; |
| } |
| } |
| public static final String SYS_MODEL = android.os.Build.MODEL; |
| public static final String EAGLE = "eagle"; |
| public static final String ENVIRONMENT = "environment"; |
| public static final String WEEX_CURRENT_KEY = "wx_current_url"; |
| /********************* |
| * Global config |
| ***************************/ |
| |
| public static String JS_LIB_SDK_VERSION = BuildConfig.buildJavascriptFrameworkVersion; |
| |
| public static String WXSDK_VERSION = BuildConfig.buildVersion; |
| public static Application sApplication; |
| public static final String DEV_Id = getDevId(); |
| @Deprecated |
| public static int sDefaultWidth = 750; |
| public volatile static boolean JsFrameworkInit = false; |
| |
| public static final String SETTING_EXCLUDE_X86SUPPORT = "env_exclude_x86"; |
| |
| public static boolean SETTING_FORCE_VERTICAL_SCREEN = false; |
| |
| /** |
| * auto adjust device width for when screen size change. |
| * */ |
| public static boolean AUTO_ADJUST_ENV_DEVICE_WIDTH = true; |
| |
| public static boolean AUTO_UPDATE_APPLICATION_SCREEN_SIZE = true; |
| |
| @RestrictTo(Scope.LIBRARY) |
| public static volatile boolean sUseRunTimeApi; |
| |
| /** |
| * Debug model |
| */ |
| public static boolean sDebugMode = false; |
| public static final boolean sForceEnableDevTool = true; |
| public static String sDebugWsUrl = ""; |
| public static boolean sDebugServerConnectable = false; |
| public static boolean sRemoteDebugMode = false; |
| public static String sRemoteDebugProxyUrl = ""; |
| public static boolean sDebugNetworkEventReporterEnable = false;//debugtool network switch |
| public static long sJSLibInitTime = 0; |
| |
| public static long sSDKInitStart = 0;// init start timestamp |
| public static long sSDKInitInvokeTime = 0;//time cost to invoke init method |
| public static long sSDKInitExecuteTime = 0;//time cost to execute init job |
| /** from init to sdk-ready **/ |
| public static long sSDKInitTime =0; |
| |
| public static long sJSFMStartListenerTime=0; |
| |
| public static volatile boolean isWsFixMode = true; |
| |
| /** |
| * component and modules ready |
| * */ |
| public static long sComponentsAndModulesReadyTime = 0; |
| |
| public static boolean sInAliWeex = false; |
| |
| public static LogLevel sLogLevel = LogLevel.DEBUG; |
| private static boolean isApkDebug = true; |
| public static boolean isPerf = false; |
| private static boolean sDebugFlagInit = false; |
| |
| private static boolean openDebugLog = true; |
| |
| private static String sGlobalFontFamily; |
| |
| public static final String CORE_SO_NAME = "weexcore"; |
| public static final String CORE_JSS_SO_NAME = "weexjss"; |
| public static final String CORE_JSB_SO_NAME = "weexjsb"; |
| public static final String CORE_JST_SO_NAME = "weexjst"; |
| |
| @RestrictTo(Scope.LIBRARY) |
| public static String CORE_JSC_SO_NAME = BuildConfig.JSInterpolatorName; |
| public static String CORE_JSS_SO_PATH = null; |
| |
| private static String CORE_JSS_ICU_PATH = null; |
| |
| private static String CORE_JSC_SO_PATH = null; |
| |
| public static String CORE_JSB_SO_PATH = null; |
| |
| private static String COPY_SO_DES_DIR = null; |
| |
| private static String LIB_LD_PATH = null; |
| |
| private static Map<String, String> options = new ConcurrentHashMap<>(); |
| static { |
| options.put(WXConfig.os, OS); |
| options.put(WXConfig.osName, OS); |
| } |
| |
| |
| public static synchronized WXDefaultSettings getWXDefaultSettings() { |
| if (mWXDefaultSettings == null && getApplication() != null) { |
| mWXDefaultSettings = new WXDefaultSettings(getApplication()); |
| } |
| return mWXDefaultSettings; |
| } |
| |
| public static synchronized String getDefaultSettingValue(String key, String defaultValue) { |
| WXDefaultSettings wxDefaultSettings = getWXDefaultSettings(); |
| if (wxDefaultSettings == null || TextUtils.isEmpty(key)) { |
| return defaultValue; |
| } |
| return wxDefaultSettings.getValue(key, defaultValue); |
| } |
| |
| public static synchronized void writeDefaultSettingsValue(String key, String value) { |
| WXDefaultSettings wxDefaultSettings = getWXDefaultSettings(); |
| if (wxDefaultSettings == null |
| || TextUtils.isEmpty(key) |
| || TextUtils.isEmpty(value)) { |
| return; |
| } |
| wxDefaultSettings.saveValue(key, value); |
| } |
| |
| private static WXDefaultSettings mWXDefaultSettings; |
| |
| /** |
| * dynamic |
| */ |
| public static boolean sDynamicMode = false; |
| public static String sDynamicUrl = ""; |
| |
| /** |
| * Fetch system information. |
| * @return map contains system information. |
| */ |
| public static Map<String, String> getConfig() { |
| Map<String, String> configs = new HashMap<>(); |
| configs.put(WXConfig.os, OS); |
| configs.put(WXConfig.appVersion, getAppVersionName()); |
| configs.put(WXConfig.cacheDir, getAppCacheFile()); |
| configs.put(WXConfig.devId, DEV_Id); |
| configs.put(WXConfig.sysVersion, SYS_VERSION); |
| configs.put(WXConfig.sysModel, SYS_MODEL); |
| configs.put(WXConfig.weexVersion, String.valueOf(WXSDK_VERSION)); |
| |
| try { |
| configs.put(WXConfig.layoutDirection, isLayoutDirectionRTL() ? "rtl" : "ltr"); |
| } catch (Exception e) { |
| configs.put(WXConfig.layoutDirection, "ltr"); |
| } |
| |
| try { |
| if (isApkDebugable()) { |
| addCustomOptions(WXConfig.debugMode, "true"); |
| } |
| addCustomOptions(WXConfig.scale, Float.toString(sApplication.getResources().getDisplayMetrics().density)); |
| addCustomOptions(WXConfig.androidStatusBarHeight, Float.toString(WXViewUtils.getStatusBarHeight(sApplication))); |
| }catch (NullPointerException e){ |
| //There is little chance of NullPointerException as sApplication may be null. |
| WXLogUtils.e("WXEnvironment scale Exception: ", e); |
| } |
| configs.putAll(getCustomOptions()); |
| if(configs.get(WXConfig.appName)==null && sApplication!=null){ |
| configs.put(WXConfig.appName, sApplication.getPackageName()); |
| } |
| return configs; |
| } |
| |
| /** |
| * Get the version of the current app. |
| */ |
| public static String getAppVersionName() { |
| String versionName = ""; |
| PackageManager manager; |
| PackageInfo info = null; |
| try { |
| manager = sApplication.getPackageManager(); |
| info = manager.getPackageInfo(sApplication.getPackageName(), 0); |
| versionName = info.versionName; |
| } catch (Exception e) { |
| WXLogUtils.e("WXEnvironment getAppVersionName Exception: ", e); |
| } |
| return versionName; |
| } |
| |
| /** |
| * |
| * @return string cache file |
| */ |
| private static String getAppCacheFile() { |
| String cache = ""; |
| try { |
| cache = sApplication.getApplicationContext().getCacheDir().getPath(); |
| } catch (Exception e) { |
| WXLogUtils.e("WXEnvironment getAppCacheFile Exception: ", e); |
| } |
| return cache; |
| } |
| |
| |
| /** |
| * Use {@link #addCustomOptions(String, String)} to add custom options. |
| * Use {@link #getCustomOptions(String)} to get custom options |
| * @return |
| */ |
| @Deprecated |
| public static Map<String, String> getCustomOptions() { |
| return options; |
| } |
| |
| public static void addCustomOptions(String key, String value) { |
| options.put(key, value); |
| } |
| |
| public static String getCustomOptions(String key){ |
| return options.get(key); |
| } |
| |
| |
| @SuppressLint("SdCardPath") |
| public static String copySoDesDir() { |
| try { |
| if (TextUtils.isEmpty(COPY_SO_DES_DIR)) { |
| if (sApplication == null) { |
| WXLogUtils.e("sApplication is null, so copy path will be null"); |
| return null; |
| } |
| |
| String dirName = "/cache/weex/libs"; |
| File desDir = null; |
| String cachePath = WXEnvironment.getApplication().getApplicationContext().getCacheDir().getPath(); |
| |
| if (TextUtils.isEmpty(cachePath)) { |
| desDir = new File(cachePath, dirName); |
| } else { |
| String pkgName = sApplication.getPackageName(); |
| String toPath = "/data/data/" + pkgName + dirName; |
| desDir = new File(toPath); |
| } |
| |
| if (!desDir.exists()) { |
| desDir.mkdirs(); |
| } |
| COPY_SO_DES_DIR = desDir.getAbsolutePath(); |
| } |
| } catch (Throwable e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| return COPY_SO_DES_DIR; |
| |
| } |
| |
| @Deprecated |
| /** |
| * Use {@link #isHardwareSupport()} if you want to see whether current hardware support Weex. |
| */ |
| public static boolean isSupport() { |
| boolean isInitialized = WXSDKEngine.isInitialized(); |
| if(!isInitialized){ |
| WXLogUtils.e("WXSDKEngine.isInitialized():" + isInitialized); |
| } |
| return isHardwareSupport() && isInitialized; |
| } |
| |
| public static boolean isLayoutDirectionRTL() { |
| // support RTL |
| if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { |
| return sApplication.getApplicationContext().getResources().getBoolean(R.bool.weex_is_right_to_left); |
| } |
| return false; |
| } |
| /** |
| * Tell whether Weex can run on current hardware. |
| * @return true if weex can run on current hardware, otherwise false. |
| * Weex has removed the restrictions on the tablet, please use {@link #isCPUSupport()} |
| */ |
| @Deprecated |
| public static boolean isHardwareSupport() { |
| if (WXEnvironment.isApkDebugable()) { |
| WXLogUtils.d("isTableDevice:" + WXUtils.isTabletDevice()); |
| } |
| return isCPUSupport(); |
| } |
| |
| /** |
| * Determine whether Weex supports the current CPU architecture |
| * @return true when support |
| */ |
| public static boolean isCPUSupport(){ |
| boolean excludeX86 = "true".equals(getCustomOptions().get(SETTING_EXCLUDE_X86SUPPORT)); |
| boolean isX86AndExcluded = WXSoInstallMgrSdk.isX86() && excludeX86; |
| boolean isCPUSupport = WXSoInstallMgrSdk.isCPUSupport() && !isX86AndExcluded; |
| if (WXEnvironment.isApkDebugable()) { |
| WXLogUtils.d("WXEnvironment.sSupport:" + isCPUSupport |
| + "isX86AndExclueded: "+ isX86AndExcluded); |
| } |
| return isCPUSupport; |
| } |
| |
| public static boolean isApkDebugable() { |
| return isApkDebugable(sApplication); |
| } |
| |
| public static boolean isApkDebugable(Application application) { |
| if (application == null) { |
| return false; |
| } |
| |
| if (isPerf) { |
| return false; |
| } |
| |
| if (sDebugFlagInit){ |
| return isApkDebug; |
| } |
| try { |
| String debugModeConfig = getCustomOptions().get(WXConfig.debugMode); |
| if (TextUtils.isEmpty(debugModeConfig)){ |
| ApplicationInfo info = application.getApplicationInfo(); |
| isApkDebug = (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0; |
| }else { |
| isApkDebug = Boolean.valueOf(debugModeConfig); |
| } |
| } catch (Exception e) { |
| /** |
| * Don't call WXLogUtils.e here,will cause stackoverflow |
| */ |
| e.printStackTrace(); |
| isApkDebug = false; |
| } |
| sDebugFlagInit = true; |
| return isApkDebug; |
| } |
| |
| public static boolean isPerf() { |
| return isPerf; |
| } |
| |
| @SuppressLint("HardwareIds") |
| private static String getDevId() { |
| String ret = ""; |
| if(sApplication != null){ |
| try{ |
| ret = ((TelephonyManager) sApplication |
| .getSystemService(Context.TELEPHONY_SERVICE)).getDeviceId(); |
| }catch (SecurityException | NullPointerException e){ |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| } |
| return ret; |
| } |
| |
| public static Application getApplication() { |
| return sApplication; |
| } |
| |
| public void initMetrics() { |
| if (sApplication == null) { |
| return; |
| } |
| } |
| |
| public static String getDiskCacheDir(Context context) { |
| if (context == null) { |
| return null; |
| } |
| String cachePath = null; |
| try { |
| if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) |
| || !Environment.isExternalStorageRemovable()) { |
| cachePath = context.getExternalCacheDir().getPath(); |
| } else { |
| cachePath = context.getCacheDir().getPath(); |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| return cachePath; |
| } |
| |
| public static String getFilesDir(Context context) { |
| if (context == null) { |
| return ""; |
| } |
| File filesDir = context.getFilesDir(); |
| String path = ""; |
| if (filesDir != null) { |
| path = filesDir.getPath(); |
| } else { |
| path = WXEnvironment.getApplication().getApplicationInfo().dataDir; |
| path += File.separator; |
| path += "files"; |
| } |
| |
| return path; |
| } |
| |
| public static String getCrashFilePath(Context context) { |
| if (context == null) { |
| return ""; |
| } |
| |
| File dir = context.getDir("crash", Context.MODE_PRIVATE); |
| if (dir == null) |
| return ""; |
| |
| String crashDir = dir.getAbsolutePath(); |
| |
| return crashDir; |
| } |
| |
| public static String getGlobalFontFamilyName() { |
| return sGlobalFontFamily; |
| } |
| |
| public static void setGlobalFontFamily(String fontFamilyName, Typeface typeface) { |
| WXLogUtils.d("GlobalFontFamily", "Set global font family: " + fontFamilyName); |
| sGlobalFontFamily = fontFamilyName; |
| if (!TextUtils.isEmpty(fontFamilyName)) { |
| if (typeface == null) { |
| TypefaceUtil.removeFontDO(fontFamilyName); |
| } else { |
| FontDO nativeFontDO = new FontDO(fontFamilyName, typeface); |
| TypefaceUtil.putFontDO(nativeFontDO); |
| WXLogUtils.d("TypefaceUtil", "Add new font: " + fontFamilyName); |
| } |
| } |
| } |
| |
| public static boolean isOpenDebugLog() { |
| return openDebugLog; |
| } |
| |
| public static void setOpenDebugLog(boolean openDebugLog) { |
| WXEnvironment.openDebugLog = openDebugLog; |
| } |
| |
| public static void setApkDebugable(boolean debugable){ |
| isApkDebug = debugable; |
| if(!isApkDebug){ |
| openDebugLog = false; |
| } |
| } |
| |
| public static String getCacheDir() { |
| final Application application = getApplication(); |
| if (application == null || application.getApplicationContext() == null) |
| return null; |
| return application.getApplicationContext().getCacheDir().getPath(); |
| } |
| |
| public static String extractSo() { |
| File sourceFile = new File(getApplication().getApplicationContext().getApplicationInfo().sourceDir); |
| final String soDesPath = copySoDesDir(); |
| if (sourceFile.exists() && !TextUtils.isEmpty(soDesPath)) { |
| try { |
| WXFileUtils.extractSo(sourceFile.getAbsolutePath(), soDesPath); |
| } catch (IOException e) { |
| WXLogUtils.e("extractSo error " + e.getMessage()); |
| // e.printStackTrace(); |
| return null; |
| } |
| return soDesPath; |
| } |
| return null; |
| } |
| |
| private static String findIcuPath() { |
| File file = new File("/proc/self/maps"); |
| BufferedReader reader = null; |
| try { |
| reader = new BufferedReader(new FileReader(file)); |
| String tempString = null; |
| while ((tempString = reader.readLine()) != null) { |
| if (tempString.contains("icudt")) { |
| |
| int i = tempString.indexOf('/'); |
| |
| String substring = tempString.substring(i); |
| return substring.trim(); |
| } |
| } |
| reader.close(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } finally { |
| if (reader != null) { |
| try { |
| reader.close(); |
| } catch (IOException e1) { |
| } |
| } |
| } |
| |
| return null; |
| } |
| |
| public static int memfd_create(String name, int size) { |
| if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) { |
| return 0; |
| } |
| |
| int fd = 0; |
| try { |
| Method memfd_create = Os.class.getMethod("memfd_create", String.class, int.class); |
| Object fd_object = memfd_create.invoke(null, name, 0); |
| if (fd_object instanceof FileDescriptor) { |
| Field descriptor = FileDescriptor.class.getDeclaredField("descriptor"); |
| descriptor.setAccessible(true); |
| Object fd_int_object = descriptor.get(fd_object); |
| fd = Integer.parseInt(String.valueOf(fd_int_object)); |
| descriptor.setAccessible(false); |
| Os.ftruncate((FileDescriptor) fd_object, size); |
| } |
| } catch (Throwable e) { |
| // do Nothing |
| } |
| return fd; |
| } |
| |
| public static String findSoPath(String libName) { |
| String soPath = ((PathClassLoader) (WXEnvironment.class.getClassLoader())).findLibrary(libName); |
| if (!TextUtils.isEmpty(soPath)) { |
| File soFile = new File(soPath); |
| if (soFile.exists()) { |
| WXLogUtils.e(libName + "'s Path is" + soPath); |
| return soFile.getAbsolutePath(); |
| } else { |
| WXLogUtils.e(libName + "'s Path is " + soPath + " but file does not exist"); |
| } |
| } |
| |
| String realName = "lib" + libName + ".so"; |
| String cacheDir = getCacheDir(); |
| if (TextUtils.isEmpty(cacheDir)) { |
| WXLogUtils.e("cache dir is null"); |
| return ""; |
| } |
| |
| |
| if (cacheDir.indexOf("/cache") > 0) { |
| soPath = new File(cacheDir.replace("/cache", "/lib"), realName).getAbsolutePath(); |
| } |
| |
| |
| final File soFile = new File(soPath); |
| if (soFile.exists()) { |
| WXLogUtils.e(libName + "use lib so"); |
| return soPath; |
| } else { |
| //unzip from apk file |
| final String extractSoPath = extractSo(); |
| if (!TextUtils.isEmpty(extractSoPath)) { |
| return new File(extractSoPath, realName).getAbsolutePath(); |
| } |
| } |
| return soPath; |
| } |
| |
| public static String getLibJScRealPath() { |
| if(TextUtils.isEmpty(CORE_JSC_SO_PATH)) { |
| CORE_JSC_SO_PATH = findSoPath(CORE_JSC_SO_NAME); |
| WXLogUtils.e("findLibJscRealPath " + CORE_JSC_SO_PATH); |
| } |
| return CORE_JSC_SO_PATH; |
| } |
| |
| public static String getLibJssRealPath() { |
| if(TextUtils.isEmpty(CORE_JSS_SO_PATH)) { |
| CORE_JSS_SO_PATH = findSoPath(CORE_JSS_SO_NAME); |
| WXLogUtils.d("test-> findLibJssRealPath " + CORE_JSS_SO_PATH); |
| } |
| |
| return CORE_JSS_SO_PATH; |
| } |
| |
| public static String getLibJssIcuPath() { |
| if(TextUtils.isEmpty(CORE_JSS_ICU_PATH)){ |
| CORE_JSS_ICU_PATH = findIcuPath(); |
| } |
| |
| return CORE_JSS_ICU_PATH; |
| } |
| |
| public static String getLibLdPath() { |
| if (TextUtils.isEmpty(LIB_LD_PATH)) { |
| ClassLoader classLoader = WXEnvironment.class.getClassLoader(); |
| try { |
| Method getLdLibraryPath = classLoader.getClass().getMethod("getLdLibraryPath", new Class[0]); |
| LIB_LD_PATH = (String) getLdLibraryPath.invoke(classLoader, new Object[0]); |
| } catch (IllegalAccessException e) { |
| e.printStackTrace(); |
| } catch (InvocationTargetException e) { |
| e.printStackTrace(); |
| } catch (NoSuchMethodException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| if(TextUtils.isEmpty(LIB_LD_PATH)) { |
| try { |
| String property = System.getProperty("java.library.path"); |
| String libJScRealPath = getLibJScRealPath(); |
| if(!TextUtils.isEmpty(libJScRealPath)) { |
| LIB_LD_PATH = new File(libJScRealPath).getParent() + ":" + property; |
| } |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| WXLogUtils.d("getLibLdPath is " + LIB_LD_PATH); |
| return LIB_LD_PATH; |
| } |
| |
| public static class WXDefaultSettings { |
| private String configName = "weex_default_settings"; |
| private SharedPreferences sharedPreferences = null; |
| public WXDefaultSettings(Application application) { |
| if(application != null) { |
| sharedPreferences = application.getSharedPreferences(configName, MODE_PRIVATE); |
| } |
| } |
| |
| public synchronized String getValue(String key, String defaultValue) { |
| if(sharedPreferences == null || TextUtils.isEmpty(key)) { |
| WXLogUtils.i("get default settings " + key + " return default value :" + defaultValue); |
| return defaultValue; |
| } |
| |
| String result = sharedPreferences.getString(key, defaultValue); |
| WXLogUtils.i("get default settings " + key + " : " + result); |
| return result; |
| } |
| |
| public synchronized void saveValue(String key, String value) { |
| if (sharedPreferences == null |
| || TextUtils.isEmpty(key) |
| || TextUtils.isEmpty(value)) { |
| return; |
| } |
| WXLogUtils.i("save default settings " + key + ":" + value); |
| SharedPreferences.Editor editor = sharedPreferences.edit(); |
| editor.putString(key, value); |
| editor.apply(); |
| } |
| } |
| } |