ionic 运行过程中动态切换API服务器地址
ionic 运行过程中动态切换API服务器地址
keywords:
ionic,phonegap,cordova,网络制式,动态切换,变更,API,服务器地址,$resource,localstorage,url
场景、需求
场景
APP以项目的形式提供,一个客户需要部署一套服务器,一个APP,所以APP的后台服务器地址不能写死。而且要求如果有wifi且在内网,需要用内网服务器地址,如果用3G或者4G,则需切换为外网服务器地址
需求
APP第一次运行,如果没有设置过服务器地址,需要设置好后台服务器地址(含内网和外网,外网是必选,内网是可选)
APP运行过程中,如果用户手机网络制式发生改变,则需要根据移动网络制式选择合适的服务器地址
原有URL的设置
以前APP的API地址,是直接写到一个constant里面,例如:
(function () {
"use strict";
angular.module("gaia.config", [])
.constant("ENV", {
"version": "1.0.1",
"name": "production",
"debug": true,
"api": "http://111.111.111.111:8088/gaia/api",
});
})();
resource的调用
var resource = $resource(ENV.api + '/customer',{},{
login:{
method:'post',
url:ENV.api + '/customer/login'
},
accesstoken:{
method:'get',
url:ENV.api + '/customer/accesstoken'
}
});
方案一
(后面实现方案有部分变动)
保留ENV,APP第一次启动将设置的url存到localstorage里面,在以后每次启动前,从localstorage里面取出来赋值给ENV.api,当网络制式发生改变时,再根据情况赋值改变ENV.api。所有与后台相关的Service 的$resource 的初始化都依赖于ENV.api。
设计的关键点:
- 启动时需要检查localstorage里面是否有url的值,没有则弹出设置页
- ENV.api的赋值一定要先于APP的启动,否则Service的$resource的url 都为空了
- Service 需要将$resource的定义封装并开放出接口,便于后期改变$resource的url定义
- 网络制式改变,ENV.api的改变,Service的$resource的重新定义
设置页面
请忽略美观(-__-)b
Service $resource 声明方式的改造:
var resource = null;
var _initResource = function(apiUrl){
resource = $resource(apiUrl + '/customer',{},{
login:{
method:'post',
url:apiUrl + '/customer/login'
},
accesstoken:{
method:'get',
url:apiUrl + '/customer/accesstoken'
}
});
};
_initResource(ENV.api);
return {
initResource:function(url){
_initResource(url);
},
.....
新增Service,统一变更$resource
每次变更就调用先设置ENV.api,再_Sys.changeResource(ENV.api);
(function () {
'use strict';
angular.module('gaia.services')
.factory('_Sys', function (ENV, User, Projects, Plans) {
return {
changeResource: function (url) {
User.initResource(url);
Projects.initResource(url);
Plans.initResource(url);
}
};
});
})();
网络制式切换,调整URL
关于网络制式的监控的相关细节见:ngcordova 监控网络制式改变
$rootScope.$on('$cordovaNetwork:online', function (event, networkState) {
var type = $cordovaNetwork.getNetwork();
if (type == Connection.WIFI) {
var wifiApi = Settings.getWIFIAPI();
if (wifiApi) {
//test方法定义见方案二Setting定义
Settings.test(wifiApi).$promise.then(function (response) {
if (response.success) {
//切换内网服务器地址中....
_Sys.changeResource(wifiApi);
}
}, function (e) {});
}
}
else if (type == Connection.CELL_4G || type == Connection.CELL_3G) {
var wlanApi = Settings.getAPI();
//切换移动网(3G|4G)服务器地址中....
_Sys.changeResource(wlanApi);
}
});
方案二
大体思路同方案一,只是在思想方案一过程中,又是localstorage 又是ENV.api,各种判断,给绕晕了,后来一想,url最终还是以localstorage里面存储的为准,何不抛弃ENV.api,实现大统一(●ˇ∀ˇ●)
设计思路改动点:
- 抛弃ENV.api,所有获取和设置,均以localstorage为准
- 简化、优化API地址的获取和设置,见下面Setting Service 的定义(新增getAPI(),getWIFIAPI())
- 所有Service $resource中的URL,均取于Setting.getAPI()方法
- 进入第一个页面前,判断Setting.getAPI()的值是否存在,不存在则弹出设置页面进行设置
1.用户设置的API地址,存储到localstorage里面,定义两个基础Service,一个用于localstorage操作,一个用于APP参数设置
//Storage Service 定义
(function(){
'use strict';
angular.module('gaia.services')
.factory('Storage',function($log){
$log.debug("Storage Service init");
return {
set:function(key,data){
return window.localStorage.setItem(key,window.JSON.stringify(data));
},
get:function(key){
return window.JSON.parse(window.localStorage.getItem(key));
},
remove:function(key){
return window.localStorage.removeItem(key);
}
};
});
})();
//Settings Service 定义
(function () {
'use strict';
angular.module('gaia.services')
.factory('Settings', function ($resource, $log, Storage) {
var storageKey = 'settings';
var _settings = Storage.get(storageKey) || {};
var addOn = '/gaia/api';
return {
getSettings: function () {
return _settings;
},
save: function (settings) {
Storage.set(storageKey, settings);
_settings = settings;//改变内存中的_settings,便于每次调用getAPI时都能取到最新值
return settings;
},
getAPI: function () {
if (_settings.wlan) {
return "http://" + _settings.wlan + addOn;
}
return "";
},
getWIFIAPI: function () {
if (_settings.wifiMode && _settings.wifi) {
return "http://" + _settings.wifi + addOn;
}
return "";
},
test: function (url) {
var resource = $resource("http://" + url + addOn + "/test", {}, {
query: {
method: 'get',
isArray: false,
timeout: 2000
}
});
return resource.query();
}
};
});
})();
2.Service $resource 的部分改动
var resource = null;
var _initResource = function(apiUrl){
resource = $resource(apiUrl + '/customer',{},{
login:{
method:'post',
url:apiUrl + '/customer/login'
},
accesstoken:{
method:'get',
url:apiUrl + '/customer/accesstoken'
}
});
};
//将此处的ENV.api 换成Settings.getAPI()
// _initResource(ENV.api);
_initResource(Settings.getAPI());
3.检测是否存在API地址,不存在则弹出设置页面
$scope.api = Settings.getAPI();
$ionicModal.fromTemplateUrl('templates/urlSetting.html', {
scope: $scope
}).then(function (modal) {
$scope.settingModal = modal;
if ((!$scope.api) || ($scope.api.indexOf("http://") === -1)) {
if (window.StatusBar) {
StatusBar.styleDefault();
}
$scope.settingModal.show();
}
});
//保存设置值方法
$scope.saveSettings = function () {
//1.save setting 到localstorage
if (!$scope.settings.wifiMode) {
$scope.settings.wifi = "";
}
Settings.save($scope.settings);
$ionicLoading.show({
noBackdrop: true,
template: "<div><h1><i class='icon ion-checkmark-circled balanced'></i></h1>保存成功</div>",
duration: 1000
});
$scope.api = Settings.getAPI();
//2.变更所有Service 中的resource
_Sys.changeResource($scope.api);
$scope.settingModal.hide();
};
总结
为了实现APP的后台API地址动态改变,只要找到问题的核心,不外乎围绕着API_URL 的获取 和设置 来实现该功能
获取:
- 判断localstroage是否存储了API_URL - 增加判断方法
- 与后台服务器请求相关的Service - 变更$resource 的定义方法,并开放出改变的接口
设置:
- localstroage里面没有API_URL ,弹出页,保存时
- 网络制式发生变化时
【原创】,转载请带上原地址http://www.cnblogs.com/sloong/p/5151019.html
ionic 运行过程中动态切换API服务器地址的更多相关文章
- HOWTO - Basic MSI安装包在安装运行过程中如何获取完整源路径
有朋友问到如何在一个Windows Installer安装包中获取安装包源路径,就是在安装包运行过程中动态获取*.msi所在完整路径. 这个问题分两类,如果我们的安装包只是一个*.msi安装文件,那么 ...
- Jmeter运行过程中如何让Fiddler同时可以抓获到服务器的应答报文
在默认情况下,Jmeter运行过程中,Fiddler是抓不到对应的应答报文的. 但是,在某些时候,我们希望分析Jmeter执行失败的原因,想了解Jmeter获取到的应答报文是否有问题,就需要同服务器返 ...
- oracle过程中动态语句实现
oracle过程中动态语句实现 一般的PL/SQL程序设计中,在DML和事务控制的语句中可以直接使用SQL,但是DDL语句及系统控制语句却不能在PL/SQL中直接使用,要想实现在PL/SQL中使用DD ...
- Torch-RNN运行过程中的坑 [1](读取Lua非空table,size为0)
0.踩坑背景 执行Torch-RNN的时候,在LanguageModel.lua中的encode_string函数中,对start_text的各个character进行id映射编码,实现功能类似“北京 ...
- Torch-RNN运行过程中的坑 [0](一些基础概念)
0.Lua & LuaJIT简介 Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua 是巴 ...
- 程序运行过程中遇到“ORA-03114: not connected to ORACLE”的问题解决
c#,winform程序,数据批量入oracle库时用到DataAdaper的.FillSchema函数,如:da.FillSchema(dt2, SchemaType.Mapped); 程序运行一段 ...
- (转)在.NET程序运行过程中,什么是堆,什么是栈?什么情况下会在堆(栈)上分配数据?它们有性能上的区别吗?“结构”对象可能分配在堆上吗?什么情况下会发生,有什么需要注意的吗?
转自:http://www.cnblogs.com/xiaoyao2011/archive/2011/09/09/2172427.html 在.NET程序运行过程中,什么是堆,什么是栈? 堆也就是托管 ...
- Torch-RNN运行过程中的坑 [2](Lua的string sub函数,读取中文失败,乱码?)
0.踩坑背景 仍然是torch-rnn/LanguageModel.lua文件中的一些问题,仍然是这个狗血的LM:encode_string函数: function LM:encode_string( ...
- log4j 日志信息的引入(通用版)——解决项目运行过程中的日志信息
定义 log4j是Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog守护进程 ...
随机推荐
- SQL中如何检查死锁
SQL中如何检查死锁 编写人:CC阿爸 2014-6-15 在日常SQL数据库的操作中,SQL偶尔会出现表被死锁的问题.比如: 在执行事务时,突然中止事务.系统肯定会锁表. 大批量数据操作时,由于网络 ...
- SQL中补0
SQL中补0 编写人:CC阿爸 2014-3-14 第一种方法: right('00000'+cast(@count as varchar),5) 其中'00000'的个数为right函数的最后参数 ...
- Vue.js学习 Item13 – 指令系统与自定义指令
基础 除了内置指令,Vue.js 也允许注册自定义指令.自定义指令提供一种机制将数据的变化映射为 DOM 行为. 可以用 Vue.directive(id, definition) 方法注册一个全局自 ...
- AppSetting ,connectionStrings配置节
<appSettings> <!-- 当前使用的学校代码 --> <add key="DefaultCompanyID" value="cs ...
- Hive中的排序语法
ORDER BY hive中的ORDER BY语句和关系数据库中的sql语法相似.他会对查询结果做全局排序,这意味着所有的数据会传送到一个Reduce任务上,这样会导致在大数量的情况下,花费大量时间. ...
- 发布阿里云OSS for phpcmsV9整合教程
说明:这个算不上是插件,因为没有安装包,需要手工修改代码. 还有一点就是后台发布文章时上传的附件还是会保存在你的服务器上,基于以下原因: 1.个人的需求是前台页面需要使用thumb函数生成多个缩略图大 ...
- arcgis api for javascript 3.16开发(一)
原来一直都在用Flex开发arcgis的地图接口,用的时间很长,用的习惯也顺手,可Flex这个开发工具已经基本要淘汰了,并且地图借助flash的方式加载在浏览器里已经不能适应webgis的快速开发需求 ...
- 强大的网络通信框架(实现缓存)--第三方开源--volley
Android Volley是Android平台上很好用的第三方开源网络通信框架.使用简答,功能强大. Android Volley的库jar包Volley.ja下载连接地址:Volley下载 下载后 ...
- appcan weixin 开发
登录微信开放平台:https://open.weixin.qq.com/ 管理中心,创建移动应用,ps:创建应用需要审核,其中 应用包名 需与在线打包安卓时候的 自定义包名一致. 开放平台 应用申请 ...
- ajax向前台输出二维数组 并解析
最近在弄一个售后数据统计的功能,里边需要统计特定时期内各种客户.机型的分布比例,单单table来计算并显示很死板(一点也不酷) 于是决定用jquery插件flot并通过ajax传输数据 :flot的折 ...