之前开发程序联测测接口的时候,因为要和不同的后台人员调接口,所以经常要先把程序里的ip地址改成后台人员给我的。每次都要先修改ip地址,之后编译运行一下,才能测试。但要是换了个后台人员,或者同时和2个后台人员测接口,又要再修改ip后重新编译,重新运行,很繁琐,包括后期测试也是一样。
测试人员总是问我能不能弄个功能,可以让他们在dat环境下测完一个功能后,可以在应用里手动切换网络地址,继续测uat网络环境下此功能是否正常,之前忙着别的事儿,而且对这个功能也没什么头绪,就一直没弄。最近时间闲下来了,而且关于这个功能,我也有了一些自己的见解,所以在此把这个功能展示一下,嘿嘿。
多余的话就不说了,直接上图~
核心原理:这个输入框里可以随时设置网络地址和端口号(如果不需要输入端口号,直接空着就行),设置的网址会在点击保存按钮后直接替换app里面通用的网络地址前缀,同时将数据存入SharedPreferences中,每次启动app时,都会从Application中先检查SharedPreferences中是否存在保存的数据,如果有存储的数据,就将通用url修改成存储的url,达到这次保存,下次就不用修改了的功能。
下面开始直接贴代码
1.MainActivity.java
public class MainActivity extends AppCompatActivity {
private TextView tv_url_ma, tv_changeurl_ma, tv_refresh_ma;
private WebView wv_showurl_ma;
private static final int INTERNETCODE = 001;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();//代码初始化
tv_url_ma.setText(PublicInfo.appurl);
setClick();//设置点击方法
checkPermissions();//检查用户是否给予网络权限,如果没有,就不启用
initwv();//webview设置
}
/*8
检查用户是否给予网络权限
*/
private void checkPermissions() {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED) {//用户没有进行网络授权
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.INTERNET}, INTERNETCODE);
return;
} else {
//已经获取到网络权限,可以显示默认网址中的数据
wv_showurl_ma.loadUrl(PublicInfo.appurl);//设置网络地址
}
}
/**
* 用户权限返回结果
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case INTERNETCODE://网络权限的返回值
//if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {//证明得到了用户授权
checkPermissions();//再次调用检查权限的方法,如果没问题,就会启动网络请求
} else {
Toast.makeText(MainActivity.this, "当前设备未获取网络权限,无法联网", Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
}
/**
* webView设置
*/
private void initwv() {
wv_showurl_ma.getSettings().setJavaScriptEnabled(true);//如果网页中使用js,不加这行代码不显示
wv_showurl_ma.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// return super.shouldOverrideUrlLoading(view, url);
view.loadUrl(url);
return true;//返回值为true时在WebView中打开,为false时调用浏览器打开
}
});
}
/**
* 设置点击方法
*/
private void setClick() {
tv_changeurl_ma.setOnClickListener(new MainActivityClicm());
tv_refresh_ma.setOnClickListener(new MainActivityClicm());
}
/**
* 代码初始化
*/
private void init() {
tv_url_ma = findViewById(R.id.tv_url_ma);//url地址展示
tv_changeurl_ma = findViewById(R.id.tv_changeurl_ma);//修改url地址按钮
tv_refresh_ma = findViewById(R.id.tv_refresh_ma);//刷新页面按钮
wv_showurl_ma = findViewById(R.id.wv_showurl_ma);//展示当前url所对应的网站详情
}
/**
* 设置本页的点击方法
*/
private class MainActivityClicm implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tv_changeurl_ma://修改url地址
// Toast.makeText(MainActivity.this,"修改url地址",Toast.LENGTH_SHORT).show();
DialogUtils dialogUtils = new DialogUtils(MainActivity.this);
if (!dialogUtils.isShow()) {//判断弹出框是否已经打开了,如果没打开过,才运行打开代码
dialogUtils.showDialog("这里输入弹出框的展示标题");
}
break;
case R.id.tv_refresh_ma://刷新页面
Toast.makeText(MainActivity.this, "刷新页面", Toast.LENGTH_SHORT).show();
wv_showurl_ma.loadUrl(PublicInfo.appurl);//设置网络地址
tv_url_ma.setText(PublicInfo.appurl);//展示当前的网络地址
break;
default:
break;
}
}
}
}
2.DialogUtils.java
/**
* 这个类里设置弹出框的数据
*/
public class DialogUtils extends Dialog {
private Context context;
private Dialog dialog;
private SharedPreferences mSharedPreferences;
private TextView tv_iptitle_udg, tv_title_udg, tv_nowurl_udg;
private Spinner sp_checkurl_udg;
private AppCompatEditText et_ipurl_udg, et_port_udg;
private AppCompatButton btn_ok_udg, btn_cancel_udg;
private ArrayAdapter<String> arrayAdapter;
//下面这三个参数,可以放到项目values下的string中,这里为了看着方便就直接写这里了
private static final String url_dat = "测试环境DAT";
private static final String url_uat = "测试环境UAT";
private static final String url_pre = "测试环境准生产";
//为SharedPreferences设置一些必要的参数
public static final String URLSETTINGINFO = "URLSETTINGINFO";
public static final String URLSETTINGIP = "URLSETTINGIP";
public static final String URLSETTINGPORT = "URLSETTINGPROT";
private SharedPreferences sharedPreferences;
public DialogUtils(@NonNull Context context) {
super(context);
this.context = context;//拿到上下文
sharedPreferences = context.getSharedPreferences(URLSETTINGINFO, Context.MODE_PRIVATE);
}
/**
* 显示dialog窗口的方法
*/
public void showDialog(String title) {
dialog = new Dialog(context);
dialog.setCancelable(false);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setContentView(R.layout.utils_dialog);
final Window window = dialog.getWindow();
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//设置背景透明
initView(dialog);//设置dialog的参数
tv_title_udg.setText(title);//设置标题
tv_nowurl_udg.setText("当前url地址为:" + PublicInfo.appurl);//设置当前url地址
tv_iptitle_udg.setText("ip地址" + PublicInfo.urltitle);
initSpinner();//设置spinner参数
setClick();//设置点击方法
dialog.show();
}
/**
* 设置点击方法
*/
private void setClick() {
btn_ok_udg.setOnClickListener(new DUtilsClick());
btn_cancel_udg.setOnClickListener(new DUtilsClick());
}
/**
* 设置spinner参数
*/
private void initSpinner() {
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add(url_dat);
arrayList.add(url_uat);
arrayList.add(url_pre);
//设置适配器
arrayAdapter = new ArrayAdapter<String>(context, android.R.layout.simple_spinner_item, arrayList);
arrayAdapter.setDropDownViewResource(R.layout.spinner_layout);//这个是设置自定义view时使用的方法,如果使用默认就可以的话,可以不用写这行代码
sp_checkurl_udg.setAdapter(arrayAdapter);
sp_checkurl_udg.setOnItemSelectedListener(new DUtilsSpinnerClick());
}
/**
* 设置dialog中的参数
*
* @param dialog
*/
private void initView(Dialog dialog) {
tv_title_udg = dialog.findViewById(R.id.tv_title_udg);//标题栏
tv_nowurl_udg = dialog.findViewById(R.id.tv_nowurl_udg);//显示当前url地址
sp_checkurl_udg = dialog.findViewById(R.id.sp_checkurl_udg);//可以设置默认地址的下拉框
tv_iptitle_udg = dialog.findViewById(R.id.tv_iptitle_udg);//ip地址段的标题,用来显示当前的请求头是hppt还是https
et_ipurl_udg = dialog.findViewById(R.id.et_ipurl_udg);//ip地址
et_port_udg = dialog.findViewById(R.id.et_port_udg);//端口号
btn_ok_udg = dialog.findViewById(R.id.btn_ok_udg);//确认按钮
btn_cancel_udg = dialog.findViewById(R.id.btn_cancel_udg);//取消按钮
}
/**
* 设置spinner的点击方法
*/
private class DUtilsSpinnerClick implements AdapterView.OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String itemname = arrayAdapter.getItem(position);
switch (itemname) {
case url_dat://选择dat标签
setInfo(PublicInfo.rul_dat);//根据选择不同的标签,为输入框中赋予不同的网络地址
break;
case url_uat://选择uat标签
setInfo(PublicInfo.rul_uat);//根据选择不同的标签,为输入框中赋予不同的网络地址
break;
case url_pre://选择pro标签
setInfo(PublicInfo.rul_pro);//根据选择不同的标签,为输入框中赋予不同的网络地址
break;
default:
break;
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
Toast.makeText(context, "没有选择任何数据", Toast.LENGTH_SHORT).show();
}
}
/**
* 设置弹出框的点击方法
*/
private class DUtilsClick implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_ok_udg://确定按钮
btn_ok_udg.setClickable(false);//先关闭点击功能,防止用户重复点击
saveUrlInfo(et_ipurl_udg.getText().toString().trim(), et_port_udg.getText().toString().trim());//保存用户选择的url地址值
setLocalInfo(et_ipurl_udg.getText().toString().trim(), et_port_udg.getText().toString().trim());//将默认的url地址替换为用户修改的url
Toast.makeText(context, "IP地址修改成功", Toast.LENGTH_SHORT).show();
dissmissDialog();//修改完成后关闭弹窗
// android.os.Process.killProcess(android.os.Process.myPid());//IP地址修改成功后关闭程序,再次开启时启用新的IP地址(代码可用可不用,根据实际情况来决定)
break;
case R.id.btn_cancel_udg://取消按钮
dissmissDialog();//关闭弹出框
break;
default:
break;
}
}
/**
* 将默认的url地址替换为用户修改的url
*/
private void setLocalInfo(String ip, String port) {
if (TextUtils.isEmpty(port)) {
PublicInfo.appurl = PublicInfo.urltitle + ip;
} else {
PublicInfo.appurl = PublicInfo.urltitle + ip + ":" + port;
}
}
}
/**
* 设置用户选择的url地址值
*/
private void saveUrlInfo(String ip, String port) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(URLSETTINGIP, ip);
editor.putString(URLSETTINGPORT, port);
editor.commit();
}
/**
* 设置对应的网络地址
*/
private void setInfo(String baseUrl) {
String[] url = baseUrl.split("\\:");
et_ipurl_udg.setText(url[0]);
et_port_udg.setText(url[1]);
}
/**
* 判断dialog是否显示
*
* @return
*/
public boolean isShow() {
if (null != dialog) {
return dialog.isShowing();
}
return false;
}
/**
* 关闭弹出框
*/
public void dissmissDialog() {
if (null != dialog) {
dialog.dismiss();
}
}
}
3.MyApplication.java
/**
* 调用SharedPreferences时需要这个文件
*/
public class MyApplication extends Application {
private SharedPreferences sharedPreferences;
public static MyApplication application;
@Override
public void onCreate() {
super.onCreate();
application = this;
initBaseUrl();//设置默认的url地址值
}
/**
* 设置默认的url地址值
*/
private void initBaseUrl() {
sharedPreferences = getSharedPreferences(DialogUtils.URLSETTINGINFO, Context.MODE_PRIVATE);
String localip = "";
String localport = "";
try {
String[] port = PublicInfo.baseurl.split("\\:");
localip = sharedPreferences.getString(DialogUtils.URLSETTINGIP, port[0]);
localport = sharedPreferences.getString(DialogUtils.URLSETTINGPORT, port[1]);
if(TextUtils.isEmpty(localport)){//如果前一次端口号存储为空,就不在网址后面追加端口号。
PublicInfo.appurl = PublicInfo.urltitle + localip;//将本地存储的URL地址设置为程序中默认的网络请求地址。
}else{
PublicInfo.appurl = PublicInfo.urltitle + localip + ":" + localport;//将本地存储的URL地址设置为程序中默认的网络请求地址。
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
4.PublicInfo.java
/**
* 这个类里存储需要调用的地址
*/
public class PublicInfo {
public static String urltitle = "https://";
public static String rul_dat = "www.baidu.com:80";
public static String rul_uat = "www.zhihu.com:80";
public static String rul_pro = "www.sina.com:80";
public static String basetitle=urltitle;//设置默认的请求头(http或者https)
public static String baseurl=rul_dat;//设置默认地址(dat,uat或者其他的)
public static String appurl=basetitle+baseurl;//这里设置app的默认网络请求地址
}
5.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="登录界面" />
<TextView
android:id="@+id/tv_url_ma"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="20dp"
android:text="当前网络地址" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
>
<TextView
android:id="@+id/tv_changeurl_ma"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="#00ff00"
android:layout_marginLeft="30dp"
android:text="修改地址" />
<TextView
android:id="@+id/tv_refresh_ma"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="#ff0000"
android:layout_alignParentRight="true"
android:layout_marginRight="30dp"
android:text="刷新页面" />
</RelativeLayout>
<WebView
android:id="@+id/wv_showurl_ma"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
6.spinner_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="spinner里面每个选项的布局"
android:gravity="center"
android:padding="10dp"
>
</TextView>
7.utils_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="340dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#ffffff"
android:orientation="vertical">
<TextView
android:id="@+id/tv_title_udg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="标题栏"
android:textSize="20sp" />
<TextView
android:id="@+id/tv_nowurl_udg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="当前的url地址:" />
<Spinner
android:id="@+id/sp_checkurl_udg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="10dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="3"
>
<TextView
android:id="@+id/tv_iptitle_udg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ip地址:"
/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_ipurl_udg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="ip地址" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="1"
android:gravity="center"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="端口号:"
/>
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/et_port_udg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:hint="端口号" />
</LinearLayout>
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_ok_udg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确定" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_cancel_udg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="取消" />
</RelativeLayout>
</LinearLayout>
8.AndroidManifest.xml(这个很重要,一个是添加了网路权限,另一个是将app默认的Application设置为上面自己设置的MyApplication,这个是很重要的,别偷懒啊)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.loginactivity">
<!-- 设置用户网络权限-->
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>