Android建立GPRS通信的流程

(1).应用程序中的入口

从settings应用程序中,选择移动网络,进入到 Phone应用程序的移动网络设置界面 (actionbar的应用程序图标可以明确看出,开始的时候以为还是在 settings程序中,直接去找,找了好半天也没有找到,最后才想起根据 settings列表的点击事件去查看执行了什么操作,才发现已经进入了 Phone程序,看来很多东西不能只凭眼睛看到的就下结论 ),在这里启用数据连接。对应源码为:
alps/packages/apps/Phone/src/com/android/phone/MobileNetworkSettings.java
现看看该类的注释:
Mobile network settings” screen. This preference screen lets you enable/disable mobile data, and control data
roaming and other network-specific mobile data features. It’s used on non-voice-capable tablets as well as regular
phone devices. Note that this PreferenceActivity is part of the phone app, even though you reach it from the “Wireless
& Networks” section of the main Settings app. It’s not part of the “Call settings” hierarchy that’s available from the
Phone app (see CallFeaturesSetting for that.)
移动网络设置界面。此首选项允许启用禁用移动数据网络,并且控制数据漫游以及其他指定的移动数据网络。它是用于 non-voice-capable平板电脑以及常规电话设备。 注意,这个PreferenceActivity 是phone应用程序 的一部分,即使你是通过 settings程序的“无线&网络”选项到达这里。这不是” Call Setting”层次结构的一部分。
//String keys for preference lookup
private static final String BUTTON_DATA_ENABLED_KEY = “button_data_enabled_key” ; //启用数据网络的key
private static final String BUTTON_DATA_USAGE_KEY = “button_data_usage_key” ;
private static final String BUTTON_PREFERED_NETWORK_MODE = “preferred_network_mode_key” ;
private static final String BUTTON_ROAMING_KEY = “button_roaming_key”;
private static final String BUTTON_CDMA_LTE_DATA_SERVICE_KEY = “cdma_lte_data_service_key” ;

通过 BUTTON_DATA_ENABLED_KEY 找到相应的 CheckBoxPreference,在onCreate() 方法中有:
@Override
protected void onCreate(Bundle icicle) {
super .onCreate(icicle);

    addPreferencesFromResource(R.xml.network_setting);

……
mDataConnPref = (DefaultSimPreference) prefSet.findPreference( KEY_DATA_CONN);
mDataConnPref .setOnPreferenceChangeListener(this);
mButtonDataEnabled = (CheckBoxPreference) prefSet.findPreference(BUTTON_DATA_ENABLED_KEY );
mButtonDataRoam = (CheckBoxPreference) prefSet.findPreference(BUTTON_ROAMING_KEY);
mButtonDataRoam .setSummaryOn(mExtension .getRoamingSummary( this,R.string.roaming_enable));
mButtonDataRoam .setSummaryOff(mExtension .getRoamingSummary( this,R.string.roaming_disable));
mButtonPreferredNetworkMode = (ListPreference) prefSet.findPreference(
BUTTON_PREFERED_NETWORK_MODE );
mButtonDataUsage = prefSet.findPreference(BUTTON_DATA_USAGE_KEY);
……
}
从oncreate方法中看到 mButtonDataEnabled 没有注册 PreferenceChangeListener事件,因此将不会触发onPreferenceChange()方法,仅触发 onPreferenceTreeClick( PreferenceScreen preferenceScreen, Preference preference)方法。在 preferenceActivity中如果监听了PreferenceChangeListener和 OnPreferenceClickListener,那么这onPreferenceTreeClick ,onPreferenceChange, onPreferenceClick三者的触发是怎么回事呢?

a.先调用onPreferenceClick() 方法,如果该方法返回 true,则不再调用onPreferenceTreeClick方法 ; 如果 onPreferenceClick方法返回false ,则继续调用 onPreferenceTreeClick方法。
b.onPreferenceChange的方法独立与其他两种方法的运行。也就是说,它总是会运行。
补充:点击某个Preference 控件后,会先回调 onPreferenceChange()方法,即是否保存值,然后再回调 onPreferenceClick以及onPreferenceTreeClick() 方法,因此在 onPreferenceClick/onPreferenceTreeClick方法中我们得到的控件值就是最新的 Preference控件值。
详细可以看: http://blog.csdn.net/qinjuning/article/details/6710003

接下来看看当前 MobileNetworkSettings的onPreferenceTreeClick 方法:
public boolean onPreferenceTreeClick( PreferenceScreen preferenceScreen, Preference preference) {

……..
else if (preference == mButtonDataEnabled) {
if (DBG ) {
log(“onPreferenceTreeClick: preference == mButtonDataEnabled.”);
}
///M: change the interface definition for consistent_UI
if (!mExtension .dataEnableReminder(mButtonDataEnabled.isChecked(), this)) {
Log.d( LOG_TAG, “onPreferenceTreeClick: preference == mButtonDataEnabled.” );
if (mButtonDataEnabled .isChecked() && isSimLocked()) {
mCellConnMgr.handleCellConn(0, PIN1_REQUEST_CODE);
Log.d( LOG_TAG, “Data enable check change request pin single card” );
mButtonDataEnabled.setChecked( false);
} else {
mIsChangeData = true ;
NetworkInfo networkInfo = mConnService.getActiveNetworkInfo();
if (!(networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI
&& networkInfo.isConnected())) {
showDialog( PROGRESS_DIALOG);
}
mConnService.setMobileDataEnabled( mButtonDataEnabled .isChecked());
mH.sendMessageDelayed( mH .obtainMessage( DATA_STATE_CHANGE_TIMEOUT), 30000);
if (mButtonDataEnabled .isChecked() &&
isNeedtoShowRoamingMsg()) {
mExtension.showWarningDlg( this,R.string.data_conn_under_roaming_hint);
}
///M: add for ATT requirement
mExtension.disableDataRoaming( mButtonDataRoam , mButtonDataEnabled.isChecked());
}
}
return true ;
}
…….
}

mConnService .setMobileDataEnabled( mButtonDataEnabled .isChecked()); 这里mConnService是 ConnectivityManager的实例,从这个方法之后,数据的启用将进入到 framework层.根据是否check决定开启或关闭数据网络。

(2).ConnectivityManager 中的setMobileDataEnabled(boolean)的调用实际是 ConnectivityService中的SetMobileDataEnable 方法
public void setMobileDataEnabled( boolean enabled) {
try {
mService.setMobileDataEnabled(enabled);
} catch (RemoteException e) {
}
}

(3).ConnectivityService 才是实际的网络管理核心。(标识 MTK的部分是MTK 进行的修改,这里可以跳过不看)该方法中先通过 enforceChangePermission()对调用程序进行是否有改变网络状态的权限的检查,如果没有,应用程序将会抛出异常被终止掉。然后发送消息 EVENT_SET_MOBILE_DATA(Message.what), 该消息将被内部类 InternalHandler的handleMessgae() 方法进行处理。
(/frameworks/base/services/java/com/android/server/ConnectivityService.java)

public void setMobileDataEnabled( boolean enabled) {
// M: To check permission for Mobile Manager Service/Application. @{
if (FeatureOption .MTK_MOBILE_MANAGEMENT) {
if (enabled && !checkMoMSSubPermission(SubPermissions.CHANGE_NETWORK_STATE_ON)) {
Slog. e(TAG, “setMobileDataEnabled(” + enabled + “) is lack of permission CHANGE_NETWORK_STATE_ON”);
return;
}
}
// @}
enforceChangePermission();
// MTK start
if (FeatureOption.MTK_GEMINI_SUPPORT) {
int curSlotId = Settings.System.getInt( mContext.getContentResolver(), Settings.System.GPRS_CONNECTION_SETTING , Settings.System.GPRS_CONNECTION_SETTING_DEFAULT ) - 1;
Log. e(“SJ”, “setMobileDataEnabled(” + enabled + “): curSlotId=” + curSlotId);
if (DBG ) Slog.d ( TAG, “setMobileDataEnabled(” + enabled + “): curSlotId=” + curSlotId);
if (enabled && (curSlotId == SimInfo. SLOT_NONE)) {
try{
mITelephony = getITelephony();
if( mITelephony == null){
Slog. e(TAG, “NULL in mITelephony”);
return;
}
for (int simId=PhoneConstants.GEMINI_SIM_1; simId

}

public boolean getAnyDataEnabled() {
final boolean result;
synchronized (mDataEnabledLock ) {
mUserDataEnabled = Settings.Global.getInt(
mPhone. getContext().getContentResolver(), Settings.Global. MOBILE_DATA, 1) == 1;
result = ( mInternalDataEnabled && sPolicyDataEnabled
&& ( mUserDataEnabled
|| ( mRequestedApnType.equals(PhoneConstants. APN_TYPE_MMS) && dataEnabled[DctConstants.APN_MMS_ID]))
&& ( enabledCount != 0));
}
if (!result && DBG ) log(“getAnyDataEnabled ” + result);
return result;
}
(9).调用onTrySetupData(String reason) 方法是DataConnectionTracker定义的抽象方法,将由其子类进行具体的实现。 DataConnectionTracker有2 个子类,分别是: GsmDataConnectionTracker和CdmaDataConnectionTracker 。这里将根据 sim支持的网络制式进行分支了。
(frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java)
(frameworks/opt/telephony/src/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java )

 GsmDataConnectionTracker 中的实现如下 :
 protected boolean onTrySetupData(String reason) {
    if (DBG ) log("onTrySetupData: reason=" + reason);     
    setupDataOnReadyApns(reason);
    return true ;
}
 CdmaDataConnectionTracker中实现如下:

protected boolean onTrySetupData(String reason) {
return trySetupData(reason);
}
两个分支中都是又调了其他的方法。 GsmDataConnectionTracker比CdmaDataConnectionTracker 多调了setupDataOnReadyApns方法,之后也会调用 trySetupdata()方法。

(10).先来看GsmDataConnectionTracker 分支,setupDataOnReadyApns(String reason)方法:根据当中的注释可知:这里循环遍历 mDataConnectionAsyncChannels 停止所有的数据链接的重连尝试闹钟。此后再一个遍历将 apnContext重置状态为idle ,以便能够执行到 trySetupdata()方法。
private void setupDataOnReadyApns (String reason) {
// Stop reconnect alarms on all data connections pending
// retry. Reset ApnContext state to IDLE.
for (DataConnectionAc dcac : mDataConnectionAsyncChannels .values()) {
if (dcac.getReconnectIntentSync() != null) {
cancelReconnectAlarm(dcac);
}
// update retry config for existing calls to match up
// ones for the new RAT.
if (dcac.dataConnection != null ) {
Collection apns = dcac.getApnListSync();

            boolean hasDefault = false ;
            for (ApnContext apnContext : apns) {
                if (apnContext.getApnType().equals(PhoneConstants. APN_TYPE_DEFAULT)) {
                    hasDefault = true;
                    break;
                }
            }
            configureRetry(dcac. dataConnection, hasDefault, 0);
        }
    }
    // Be sure retry
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值