在开发项目的过程中,通常会遇到开发环境、测试环境、预发布环境、生产环境等多种环境互相切换的问题。客户端需要根据不同环境选择不同的域名调用接口,或者展示一些隐藏功能。如果每切换一种环境都需要重新打包,那就变得太蛋疼了。
简单的说下思路,就是把需要更改的域名以文件形式存到SD卡里,通过修改/读取文件设置域名。
解决方法分为以下几步:
区分正式包、测试包:
抽象来看,其实安装包只需要两种就行:正式包、测试包。
productFlavors { dev { manifestPlaceholders.put("TEST_SETTING", "true") } prod{ manifestPlaceholders.put("TEST_SETTING", "false") }}创建app/src/main/assets/config.properties文件,内容如下:
log=falsehost=http://www.xxx.com修改AndroidManifest.xml
<meta-data android:name="TEST_SETTING" android:value="${TEST_SETTING}"></meta-data>创建工具类,用来读取存储在SDCard的自定义域名
import android.content.Context;import android.content.pm.ApplicationInfo;import android.content.pm.PackageManager;import android.os.Environment;import android.text.TextUtils;import android.util.Log;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.util.Properties;public class HttpUtil { public static final String TAG = "HttpUtil"; public static Context context; public static void init(Context context) { HttpUtil.context = context; } /** * 获取Assets目录下prance.properties中的属性 * * @param key * @return */ public static String getAssetsProperties(String key) { Context context = HttpUtil.context; String result = ""; try { Properties properties = new Properties(); InputStream is = context.getAssets().open(getPathName()); properties.load(is); if (properties != null) { if (properties.containsKey(key)) { result = properties.get(key).toString(); } } } catch (Exception e) { Log.d(TAG, "getAssetsProperties e[" + e + "]"); } return result; } /** * 读取本地SD卡文件下prance.properties中的属性 * * @param * @return */ private static String getSDcardProperties(String key) { String result = ""; try { Properties properties = new Properties(); InputStream is = new FileInputStream(getBaseDir() + getPathName()); properties.load(is); if (properties != null) { if (properties.containsKey(key)) { result = properties.get(key).toString(); } } } catch (Exception e) { e.printStackTrace(); } return result; } /** * 初始化 prance.properties中的属性 * * @param key * @return */ public static String getPropertiesValue(String key) { Context context = HttpUtil.context; String result = ""; boolean settingOpen = false; try { ApplicationInfo appInfo = context.getPackageManager() .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); String msg = appInfo.metaData.getString(Constants.TEST_SETTING); if (!TextUtils.isEmpty(msg) && msg.equals("true")) { settingOpen = true; } else { settingOpen = false; } } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } if (checkSaveLocationExists() && fileIsExists(getBaseDir() + getPathName()) && settingOpen) { result = getSDcardProperties(key); if (result.equals("")) { result = getAssetsProperties(key); } } else { result = getAssetsProperties(key); } return result; } /** * 判断文件是否存在 * * @return */ public static boolean fileIsExists(String pathName) { try { File f = new File(pathName); if (!f.exists()) { return false; } } catch (Exception e) { return false; } return true; } /** * 初始属性的文件名 * * @return */ public static String getPathName() { return "config.properties"; } /** * 检查是否安装SD卡 * * @return */ public static boolean checkSaveLocationExists() { String sDCardStatus = Environment.getExternalStorageState(); boolean status; if (sDCardStatus.equals(Environment.MEDIA_MOUNTED)) { status = true; } else status = false; return status; } /** * 初始化文件保存基本目录 * * @return */ public static String getBaseDir() { return Environment.getExternalStorageDirectory().getPath() + File.separator; }}应用,请忽略Retrofit,关注第二行。
Retrofit retrofit = new Retrofit.Builder() .baseUrl(UrlUtil.getPropertiesValue("host") + File.separator) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson)) .client(client) .build();修改,这里只有最核心的修改代码,你应该有一个可视化界面,上面有host的输入框,动态修改host。
public void setting(String host) { Properties prop = new Properties(); prop.put("host", host); saveToSDCard(prop);}private void saveToSDCard(Properties prop) { if (HttpUtil.checkSaveLocationExists()) { File file = new File(HttpUtil.getBaseDir()); if (!file.exists()) { file.mkdirs(); } try { FileOutputStream fos = new FileOutputStream(HttpUtil.getBaseDir() + HttpUtil.getPathName(), false); prop.store(fos, null); } catch (Exception e) { e.printStackTrace(); } //接下来根据需求,清理数据,然后重启APP进程 //Clear Data //Restart Process } else { ToastUtil.getInstance().showToast("保存失败,无SD卡"); }}大功告成
如果你觉得本文对你有帮助,请分享给你的好友吧~