- 浏览: 355847 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
nglxl:
点赞啊,必须点赞!!深度好文,解决了困扰我多年的疑惑。
tcp 长连接与短连接 -
cofftech:
opengl源码http://www.eyesourcecod ...
OPenGL ES 关键API小结 -
mail_j:
不是很好用,很多情况都不能处理 1、没有区分关键字的大小写2、 ...
Java解析sql语句,分析出调用到的所有表 -
a455642158:
就算监听到变成了cmwap还不行,还得监听网络连接状态Stat ...
android APN切换cmwap实现 -
xuhl1022:
看了您的android 4篇 浏览器二次开发,感触颇深,写的很 ...
Android浏览器Browser二次开发(四)浏览器中的APN切换
第四章 浏览器中的APN切换
业务需求:有些链接需要使用CMWAP接入点才能成功访问, 我们的浏览器必须能够自动切换CNNET, CMWAP.
分析:调用浏览器的时候在Intent中传递一个参数, 用于标示接入点需要。 我们的浏览器需要处理3种情况, 第一是参数为cmwap时, 切换成cmwap; 第二是参数为cmnet或者从桌面上的浏览器图标点击, 第一次启动浏览器时, 切换成cmnet; 第三是打开一个链接, 没有参数时, 不做切换, 直接使用当前接入点。 如果已经打开浏览器, 并且切换成cmwap, 无论后来如何去手动设置接入点, 当点击浏览器里面的链接, 或者输入其他地址进行访问时, 必须能够再次切换成wap. 已经打开为cmnet浏览器同理。 在需要切换的时候, 必须等到切换完成, 新的接入点成功连接上以后才能开始数据的载入。
改动: 1. 接入点切换方法
/*
* change current network connection to cmwap if it's not. added by Qkf36923
*/
public int forceAPNConnection(String apnName) {
//validate apn name.
if (apnName == null || apnName.equals("") ||
(!("cmwap".equals(apnName)||"cmnet".equals(apnName)))) {
return 0;
}
NetworkInfo info = conManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (!info.isAvailable()) {
return 0;
}
info = conManager.getActiveNetworkInfo();
String tempAPN = info == null ? "" : info.getExtraInfo();
//if current apn is not cmwap, we have to switch to cmwap.
if (!apnName.equals(tempAPN)) {
if (mNChangeReceiver != null) {
this.unregisterReceiver(mNChangeReceiver);
}
mNChangeReceiver = new NetworkChangeReceiver();
//register receiver for wap network connection.
IntentFilter upIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mNChangeReceiver, upIntentFilter);
updateCurrentAPN(getContentResolver(), apnName);
return 1;
}
return 0;
}
在onCreate和onNewIntent的方法中去判断是否需要切换, 以及设置一些标示。
public void onCreate(Bundle icicle) {
…
if (!mTabControl.restoreState(icicle)) {
// clear up the thumbnail directory if we can't restore the state as
// none of the files in the directory are referenced any more.
new ClearThumbnails().execute(
mTabControl.getThumbnailDir().listFiles());
// there is no quit on Android. But if we can't restore the state,
// we can treat it as a new Browser, remove the old session cookies.
CookieManager.getInstance().removeSessionCookie();
final Intent intent = getIntent();
final Bundle extra = intent.getExtras();
// Create an initial tab.
// If the intent is ACTION_VIEW and data is not null, the Browser is
// invoked to view the content by another application. In this case,
// the tab will be close when exit.
UrlData urlData = getUrlDataFromIntent(intent, null);
/*
* when request connection is specified to cmwap, we have to change current APN
* added by Qkf36923, 20110113
*/
String requestConType = intent.getStringExtra("data_connection");
if (requestConType == null) {
//if launched from launcher, it's treated as WWW browser
if (intent.getAction().equals(Intent.ACTION_MAIN)) {
dataConnectionType = "cmnet";
} else {
//get current APN type and set it to browser
if (info != null) {
String tempAPN = info.getExtraInfo();
dataConnectionType = tempAPN;
}
}
if (forceAPNConnection(dataConnectionType) == 1) {
isSwitchingToNet = true;
}
} else if ("cmwap".equals(requestConType)
&& info != null && (!"cmwap".equals(info.getExtraInfo()))) {
dataConnectionType = "cmwap";
if (forceAPNConnection(dataConnectionType) == 1) {
isSwitchingToWap = true;
}
}
下面会去调用loadUrl和loadDataIn方法, 需要做相应修改:
private void loadUrl(WebView view, String url) {
updateTitleBarForNewLoad(view, url);
/**if url is navigation page, we can load it from local directly.
* Added by QuYueting 20110310. Start.
*/
if (mNChangeReceiver != null) {
if (BrowserSettings.NAVIGATION_PAGE_URL.equals(url)
|| (url != null && url.startsWith("about:"))) {
autoLoad = true;
view.loadUrl(url);
} else {
autoLoad = false;
mWebView = view;
tempUrl = url;
}
} else {
view.loadUrl(url);
}
/**Added by QuYueting 20110310. End**/
}
LoadUrlDataIn方法同时也会被onNewIntent调用。
private void loadUrlDataIn(Tab t, UrlData data) {
//if it's not called from OnCreate and it's switching to wap, postpone data loading. added by Qkf36923
updateTitleBarForNewLoad(t.getWebView(), data.mUrl);
/**if no need to switch or home page is set as empty, we should load navigation page instantly.
* Added by QuYueting 20110310. Start**/
if (mNChangeReceiver == null ||
(data.isEmpty() && mSettings.getHomePage().equals(""))
|| (BrowserSettings.NAVIGATION_PAGE_URL.equals(data.mUrl))
|| (data.mUrl != null && data.mUrl.startsWith("about:"))) {
data.loadIn(t);
} else {
mt = t;
mUrlData = data;
}
/**if no need to switch or home page is set as empty, we should load navigation page instantly.
* Added by QuYueting 20110310. End**/
}
再看对OnNewIntent的修改
protected void onNewIntent(Intent intent) {
…
UrlData urlData = getUrlDataFromIntent(intent, current);
//get request connection type, if current connection type is cmwap, it indicates
//this is monternet browser, we won't change APN any more.
String requestConType = intent.getStringExtra("data_connection");
if (requestConType == null) {
//get current APN, set browser connection type.
NetworkInfo network = conManager.getActiveNetworkInfo();
if (network != null && network.isAvailable()) {
dataConnectionType = network.getExtraInfo();
}
} else if ("cmwap".equals(requestConType) || "cmnet".equals(requestConType)){
dataConnectionType = requestConType;
if (forceAPNConnection(dataConnectionType) == 1) {
if ("cmwap".equals(requestConType)) {
isSwitchingToWap = true;
}
if ("cmnet".equals(requestConType)) {
isSwitchingToNet = true;
}
}
}
fromNewIntent = true;
fromNewIntent用来标志是否是第一次创建浏览器, 这在连接上目标APN网络以后如何打开页面有关系。
下面是NetworkChangeReceiver的定义
/*
* receiver for observing network connection change, added by Qkf36923
*/
public class NetworkChangeReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
//NetworkInfo info = conManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo info = intent.getParcelableExtra(
ConnectivityManager.EXTRA_NETWORK_INFO);
String apn = info.getExtraInfo();
if (((isSwitchingToWap && "cmwap".equals(apn))
|| (isSwitchingToNet && "cmnet".equals(apn)))
&& info.isConnected() && info.isAvailable()) {
/*
* apn change message is sent out more than once during a second, but it
* only happens once practically.
*/
if(mNChangeReceiver != null) {
WebView.disablePlatformNotifications();
WebView.enablePlatformNotifications();
if (fromNewIntent) {
loadUrlOnNewIntent();
} else {
if (!autoLoad) {
loadUrlOnCreate();
autoLoad = true;
}
}
BrowserActivity.this.unregisterReceiver(mNChangeReceiver);
mNChangeReceiver = null;
Message message = connectionHandler.obtainMessage(0);
connectionHandler.sendMessageDelayed(message, 300);
}
}
}
}
}
//load data when on Create. added by Qkf36923
private void loadUrlOnCreate() {
if (mUrlData.isEmpty()) {
if (mWebView != null) {
mWebView.loadUrl(tempUrl);
mWebView = null;
}
} else {
if (mUrlData != null) {
mUrlData.loadIn(mt);
mUrlData = null;
}
}
}
private void loadUrlOnNewIntent() {
//updateTitleBarForNewLoad(mt.getWebView(), mUrlData.mUrl);
mUrlData.loadIn(mt);
}
//new handler for setting wap switching flag. added by Qkf36923
Handler connectionHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (receivedByStateListener) {
receivedByStateListener = false;
resetSwitchingFlag();
} else {
Message message = connectionHandler.obtainMessage(0);
connectionHandler.sendMessageDelayed(message, 300);
}
}
};
connectionHandler用于发送消息重置isSwitchingToWap和isSwitchingToNet标志。 因为本来浏览器中有一个网络监听器, 用于弹出网络是否存在的提示框。 我们进行接入点切换时网络会先断掉, 会被那个监听器收到, 从而弹出网络不存在的提示框, 这样用户体验不好,我们需要在切换的时候屏蔽掉。 所以做了以下修改:
mNetworkStateIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
ConnectivityManager.CONNECTIVITY_ACTION)) {…
if (!isSwitchingToWap && !isSwitchingToNet) {
onNetworkToggle(info.isAvailable());
} else {
这样当网络连接成功后, 我们需要把标志再重置回去。
业务需求:有些链接需要使用CMWAP接入点才能成功访问, 我们的浏览器必须能够自动切换CNNET, CMWAP.
分析:调用浏览器的时候在Intent中传递一个参数, 用于标示接入点需要。 我们的浏览器需要处理3种情况, 第一是参数为cmwap时, 切换成cmwap; 第二是参数为cmnet或者从桌面上的浏览器图标点击, 第一次启动浏览器时, 切换成cmnet; 第三是打开一个链接, 没有参数时, 不做切换, 直接使用当前接入点。 如果已经打开浏览器, 并且切换成cmwap, 无论后来如何去手动设置接入点, 当点击浏览器里面的链接, 或者输入其他地址进行访问时, 必须能够再次切换成wap. 已经打开为cmnet浏览器同理。 在需要切换的时候, 必须等到切换完成, 新的接入点成功连接上以后才能开始数据的载入。
改动: 1. 接入点切换方法
/*
* change current network connection to cmwap if it's not. added by Qkf36923
*/
public int forceAPNConnection(String apnName) {
//validate apn name.
if (apnName == null || apnName.equals("") ||
(!("cmwap".equals(apnName)||"cmnet".equals(apnName)))) {
return 0;
}
NetworkInfo info = conManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
if (!info.isAvailable()) {
return 0;
}
info = conManager.getActiveNetworkInfo();
String tempAPN = info == null ? "" : info.getExtraInfo();
//if current apn is not cmwap, we have to switch to cmwap.
if (!apnName.equals(tempAPN)) {
if (mNChangeReceiver != null) {
this.unregisterReceiver(mNChangeReceiver);
}
mNChangeReceiver = new NetworkChangeReceiver();
//register receiver for wap network connection.
IntentFilter upIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
registerReceiver(mNChangeReceiver, upIntentFilter);
updateCurrentAPN(getContentResolver(), apnName);
return 1;
}
return 0;
}
在onCreate和onNewIntent的方法中去判断是否需要切换, 以及设置一些标示。
public void onCreate(Bundle icicle) {
…
if (!mTabControl.restoreState(icicle)) {
// clear up the thumbnail directory if we can't restore the state as
// none of the files in the directory are referenced any more.
new ClearThumbnails().execute(
mTabControl.getThumbnailDir().listFiles());
// there is no quit on Android. But if we can't restore the state,
// we can treat it as a new Browser, remove the old session cookies.
CookieManager.getInstance().removeSessionCookie();
final Intent intent = getIntent();
final Bundle extra = intent.getExtras();
// Create an initial tab.
// If the intent is ACTION_VIEW and data is not null, the Browser is
// invoked to view the content by another application. In this case,
// the tab will be close when exit.
UrlData urlData = getUrlDataFromIntent(intent, null);
/*
* when request connection is specified to cmwap, we have to change current APN
* added by Qkf36923, 20110113
*/
String requestConType = intent.getStringExtra("data_connection");
if (requestConType == null) {
//if launched from launcher, it's treated as WWW browser
if (intent.getAction().equals(Intent.ACTION_MAIN)) {
dataConnectionType = "cmnet";
} else {
//get current APN type and set it to browser
if (info != null) {
String tempAPN = info.getExtraInfo();
dataConnectionType = tempAPN;
}
}
if (forceAPNConnection(dataConnectionType) == 1) {
isSwitchingToNet = true;
}
} else if ("cmwap".equals(requestConType)
&& info != null && (!"cmwap".equals(info.getExtraInfo()))) {
dataConnectionType = "cmwap";
if (forceAPNConnection(dataConnectionType) == 1) {
isSwitchingToWap = true;
}
}
下面会去调用loadUrl和loadDataIn方法, 需要做相应修改:
private void loadUrl(WebView view, String url) {
updateTitleBarForNewLoad(view, url);
/**if url is navigation page, we can load it from local directly.
* Added by QuYueting 20110310. Start.
*/
if (mNChangeReceiver != null) {
if (BrowserSettings.NAVIGATION_PAGE_URL.equals(url)
|| (url != null && url.startsWith("about:"))) {
autoLoad = true;
view.loadUrl(url);
} else {
autoLoad = false;
mWebView = view;
tempUrl = url;
}
} else {
view.loadUrl(url);
}
/**Added by QuYueting 20110310. End**/
}
LoadUrlDataIn方法同时也会被onNewIntent调用。
private void loadUrlDataIn(Tab t, UrlData data) {
//if it's not called from OnCreate and it's switching to wap, postpone data loading. added by Qkf36923
updateTitleBarForNewLoad(t.getWebView(), data.mUrl);
/**if no need to switch or home page is set as empty, we should load navigation page instantly.
* Added by QuYueting 20110310. Start**/
if (mNChangeReceiver == null ||
(data.isEmpty() && mSettings.getHomePage().equals(""))
|| (BrowserSettings.NAVIGATION_PAGE_URL.equals(data.mUrl))
|| (data.mUrl != null && data.mUrl.startsWith("about:"))) {
data.loadIn(t);
} else {
mt = t;
mUrlData = data;
}
/**if no need to switch or home page is set as empty, we should load navigation page instantly.
* Added by QuYueting 20110310. End**/
}
再看对OnNewIntent的修改
protected void onNewIntent(Intent intent) {
…
UrlData urlData = getUrlDataFromIntent(intent, current);
//get request connection type, if current connection type is cmwap, it indicates
//this is monternet browser, we won't change APN any more.
String requestConType = intent.getStringExtra("data_connection");
if (requestConType == null) {
//get current APN, set browser connection type.
NetworkInfo network = conManager.getActiveNetworkInfo();
if (network != null && network.isAvailable()) {
dataConnectionType = network.getExtraInfo();
}
} else if ("cmwap".equals(requestConType) || "cmnet".equals(requestConType)){
dataConnectionType = requestConType;
if (forceAPNConnection(dataConnectionType) == 1) {
if ("cmwap".equals(requestConType)) {
isSwitchingToWap = true;
}
if ("cmnet".equals(requestConType)) {
isSwitchingToNet = true;
}
}
}
fromNewIntent = true;
fromNewIntent用来标志是否是第一次创建浏览器, 这在连接上目标APN网络以后如何打开页面有关系。
下面是NetworkChangeReceiver的定义
/*
* receiver for observing network connection change, added by Qkf36923
*/
public class NetworkChangeReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
//NetworkInfo info = conManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
NetworkInfo info = intent.getParcelableExtra(
ConnectivityManager.EXTRA_NETWORK_INFO);
String apn = info.getExtraInfo();
if (((isSwitchingToWap && "cmwap".equals(apn))
|| (isSwitchingToNet && "cmnet".equals(apn)))
&& info.isConnected() && info.isAvailable()) {
/*
* apn change message is sent out more than once during a second, but it
* only happens once practically.
*/
if(mNChangeReceiver != null) {
WebView.disablePlatformNotifications();
WebView.enablePlatformNotifications();
if (fromNewIntent) {
loadUrlOnNewIntent();
} else {
if (!autoLoad) {
loadUrlOnCreate();
autoLoad = true;
}
}
BrowserActivity.this.unregisterReceiver(mNChangeReceiver);
mNChangeReceiver = null;
Message message = connectionHandler.obtainMessage(0);
connectionHandler.sendMessageDelayed(message, 300);
}
}
}
}
}
//load data when on Create. added by Qkf36923
private void loadUrlOnCreate() {
if (mUrlData.isEmpty()) {
if (mWebView != null) {
mWebView.loadUrl(tempUrl);
mWebView = null;
}
} else {
if (mUrlData != null) {
mUrlData.loadIn(mt);
mUrlData = null;
}
}
}
private void loadUrlOnNewIntent() {
//updateTitleBarForNewLoad(mt.getWebView(), mUrlData.mUrl);
mUrlData.loadIn(mt);
}
//new handler for setting wap switching flag. added by Qkf36923
Handler connectionHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (receivedByStateListener) {
receivedByStateListener = false;
resetSwitchingFlag();
} else {
Message message = connectionHandler.obtainMessage(0);
connectionHandler.sendMessageDelayed(message, 300);
}
}
};
connectionHandler用于发送消息重置isSwitchingToWap和isSwitchingToNet标志。 因为本来浏览器中有一个网络监听器, 用于弹出网络是否存在的提示框。 我们进行接入点切换时网络会先断掉, 会被那个监听器收到, 从而弹出网络不存在的提示框, 这样用户体验不好,我们需要在切换的时候屏蔽掉。 所以做了以下修改:
mNetworkStateIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(
ConnectivityManager.CONNECTIVITY_ACTION)) {…
if (!isSwitchingToWap && !isSwitchingToNet) {
onNetworkToggle(info.isAvailable());
} else {
这样当网络连接成功后, 我们需要把标志再重置回去。
评论
1 楼
xuhl1022
2012-11-09
看了您的android 4篇 浏览器二次开发,感触颇深,写的很精彩,同时我又有几个问题,想请教一下:第一:怎么给内置浏览器增加一个导航的主页?第二:我将内置浏览器,独立的编译出来了,但是只能在特定的sdk版本中运行,比如:我使用Android 2.3.3版本的sdk编译的apk,它只能在android 2.3.3模拟器里运行,其他的任何版本都不可以。我想让我的浏览器支持多个版本的sdk该怎么做?
发表评论
-
基于Java NIO的手机答题游戏开发
2014-03-31 17:59 1701先上个游戏截图: 豌豆荚地址: http://apps.w ... -
enable android deviceconnection under linux
2013-04-24 15:45 956开发环境搭建完毕,Eclipse,Java,ADT都已经折腾 ... -
set CCache for building android source code
2013-04-24 15:14 1146Setting up ccache You can opti ... -
android 源码下载403 forbidden, 406 not acceptable 错误
2013-04-24 08:46 2410解决方法 1. 浏览器登录https://android.g ... -
ubuntu11.10 编译android4.0 错处
2013-04-08 21:45 1182今天使用ubuntu11.10编译android4.0出现以下 ... -
常用WebService列表
2013-01-31 23:22 2597快递查询接口 http://webservice.36wu.c ... -
startActivityForResult 无响应问题
2013-01-24 13:57 3711今天开发遇到了个问题, 就是从一个Activity中使用sta ... -
Android中仿新浪微博刷新列表
2012-11-22 17:35 7307大家看到新浪微博中的列表往下拉的时候, 头部出现正在刷新,然后 ... -
Grid调整间距
2012-09-29 08:52 1677今天使用GridView, 发现点中某一Item时选中部分的背 ... -
android gallery和Animation组合使用, 看美女美图
2012-09-11 21:01 4330今天主要探究Gallery和Animation的使用。 制作一 ... -
Android执行 shell command
2012-03-24 17:00 7210Android执行shell命令 一、方法 1. /* ... -
BBBBBB111
2012-03-23 11:42 10陈波: 本周:代码review,解决findbugs中bug以 ... -
MonkeyTestError
2012-03-21 10:15 903-20 21:36:42.439 W/dalvikvm( ... -
INSTALL_FAILED_OLDER_SDK ERROR
2012-03-12 15:52 4385Install APK with adb: $ platfo ... -
4.0源码编译问题
2012-03-07 17:12 31141、fatal error: GL/glx.h: No suc ... -
4.0 编译apk中无classes.dex
2012-03-07 17:11 3894下载完android 4.0代码,模拟器里面的gallery不 ... -
Android 4.0源码编译错误
2012-03-05 10:19 2536UNEXPECTED TOP-LEVEL EXCEPTION: ... -
AndroidLockScreenDemo
2012-02-18 15:54 919锁屏解锁的成功案例。 -
G14 root权限获取
2012-02-13 23:36 2817HTC G14 ROOT权限获取后就能删除系统自带的程序,相信 ... -
锁屏d ds
2011-12-15 00:49 831private final IDevicePolicyMana ...
相关推荐
基于android2.2的apn开发,可以自己改写并通过第三方软件在来设置apn从而达到自己想要的结果。
android APN开发流程
Android开发之系统信息【5】——获取APN列表Android开发之系统信息【5】——获取APN列表
Android AT命令与APN开发流程分析
Android 自带应用网页浏览器代码Browser
Android APN开发流程分析
android apn切换程序,支持最新版的安卓系统,绝对好用,下载下来收藏吧
android 全面解析apn
Android的数据连接是基于PPP方式的,主要步骤为:首先通过AT命令激活PDP连接,然后利用pppd通过数据端口完成拨号连接; 数据连接的核心控制类是DataConnectionTracker,存在于GSMPhone里,数据连接不需要用户的干预...
设置android的APN配置,移动2G和联通的2G和3G网络配置,以及MMS的APN配置
在手机上插入APN,并切换到当前的APN节点,详细源码,经手机测试过,线用于公司的项目上
android端通过代码实现apn配置,这里做一下记录,方便以后查看这部分实现内容
android 设置apn,包括自动和手动,成熟代码
在android代码中切换网络,如cmnet,cmwap
iphone手机软件。可以在cmwap和cmnet切换,方便 再更改
可以将Android中APN文件转化为windowphones8中的APN文件,因为APN数量过多,所以不用手动转化,方便极了。
在HTC三星摩托手机均试验过,网上关于GPRS/3G开关的资源非常少,贴出来与到家一起学习,不好的地方请指正!
海卓APN切换开关_HIAPN_2[1].0.7.apk,能够实现手机APN的手动开关。
Laravel开发-laravel-apn-push 向Apple设备推送Laravel通知
附件为apndemo,apn.xml需放到U盘或者sd卡根目录,在有信号的时候插卡或U盘3秒后配置成功