Android 测试环境和生产环境动态切换实现思路

        在开发项目的过程中,通常会遇到开发环境、测试环境、预发布环境、生产环境等多种环境互相切换的问题。客户端需要根据不同环境选择不同的域名调用接口,或者展示一些隐藏功能。如果每切换一种环境都需要重新打包,那就变得太蛋疼了。

简单的说下思路,就是把需要更改的域名以文件形式存到SD卡里,通过修改/读取文件设置域名。

解决方法分为以下几步:



  1. 区分正式包、测试包:

抽象来看,其实安装包只需要两种就行:正式包、测试包。

productFlavors {
    dev {
        manifestPlaceholders.put("TEST_SETTING""true")
    }
    prod{
        manifestPlaceholders.put("TEST_SETTING""false")
    }
}



创建app/src/main/assets/config.properties文件,内容如下:

log=false
host=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卡");
    }
}



大功告成

如果你觉得本文对你有帮助,请分享给你的好友吧~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值