这些天一直在调系统原生的Settings.apk里面APN配置的问题,在设置里面手动增加了APN配置选项,但是在界面上还是看不到。所以跟了下代码,原以为就是简单的页面显示的问题,这一跟不要紧,一下就快追到HAL层去了(NND).
首先看Settings.apk的源码,位于packages/apps/Settings/src/com/android/settings/目录下:首先找到ApnSettings类,继承于PreferenceActivity,并实现了Preference.OnPreferenceChangeListener接口。PreferencesActivity是Android中专门用来实现程序设置界面及参数存储的一个Activity,这里就不再赘述了。
public class ApnSettings extends PreferenceActivity implements Preference.OnPreferenceChangeListener { // 恢复出厂设置的URI public static final String RESTORE_CARRIERS_URI = "content://telephony/carriers/restore"; // 普通URI,用于ContentPrivoder保存着APN配置信息 public static final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn"; private static final Uri DEFAULTAPN_URI = Uri.parse(RESTORE_CARRIERS_URI); private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI); // 两个句柄,用于恢复出厂设置 private RestoreApnUiHandler mRestoreApnUiHandler; private RestoreApnProcessHandler mRestoreApnProcessHandler; private String mSelectedKey; // 组播接收的Intent过滤器 private IntentFilter mMobileStateFilter; private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals( TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { Phone.DataState state = getMobileDataState(intent); switch (state) { case CONNECTED: if (!mRestoreDefaultApnMode) { fillList(); } else { showDialog(DIALOG_RESTORE_DEFAULTAPN); } break; } } } }; @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); // 在activity创建的时候根据xml文件来配置视图, // 实际上 res/xml/apn_settings.xml这个文件就是一个空的PreferenceScreen addPreferencesFromResource(R.xml.apn_settings); getListView().setItemsCanFocus(true); // 如果有List则获得焦点 // 这个创建一个Inter 过滤器,过滤的动作为 ACTION_ANY_DATA_CONNECTION_STATE_CHANGED mMobileStateFilter = new IntentFilter( TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); } @Override protected void onResume() { super.onResume(); // 注册一个广播接受者 registerReceiver(mMobileStateReceiver, mMobileStateFilter); if (!mRestoreDefaultApnMode) { // 如果不是恢复出厂设置 fillList(); // 填充Activity的ListView } else { showDialog(DIALOG_RESTORE_DEFAULTAPN); } } }
1) 这里首先在onCreate()方法中,根据apn_settings.xml文件来配置界面的视图,实际上就是一个PreferenceScreen。创建一个Intent过滤器, 过滤动作为ACTION_ANY_DATA_CONNECTION_STATE_CHANGED。
2) 然后在onResume()方法中,注册一个广播接受者,当收到上面的ACTION_ANY_DATA_CONNECTION_STATE_CHANGED动作时,调用
mMobileStateReceiver的onReceive()方法。其目的是为了,当我们进入APN设置的时候,这是再插上SIM卡能显示出APN的配置信息。然后判断是不是需要恢复出厂设置,如果不是,则调用fillList()方法填充当前Activity,显示出APN的配置信息。
3) 首先获取系统属性gsm.sim.operator.numeric,根据这个参数通过系统提供的ContentProvider查询数据库(位于/data/data/com.android.providers.Telephony下的telephony.db数据库中carriers表中),获得对应的配置信息。然后将其填充到每一个ApnPreference中,最后将每个ApnPreference显示到当前的PreferenceGroup上。
private void fillList() { // 获取系统的gsm.sim.operator.numeric 属性 String where = "numeric=\"" + android.os.SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "")+ "\""; // 调用系统提供的ContentProvider查询数据库 Cursor cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] { "_id", "name", "apn", "type"}, where, null, Telephony.Carriers.DEFAULT_SORT_ORDER); // 找到当前Activity中的PreferenceGroup PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list"); apnList.removeAll(); ArrayList<Preference> mmsApnList = new ArrayList<Preference>(); mSelectedKey = getSelectedApnKey(); cursor.moveToFirst(); // 迭代查询数据库 while (!cursor.isAfterLast()) { String name = cursor.getString(NAME_INDEX); String apn = cursor.getString(APN_INDEX); String key = cursor.getString(ID_INDEX); String type = cursor.getString(TYPES_INDEX); // 新建一个 ApnPreference,填充里面控件的值 ApnPreference pref = new ApnPreference(this); pref.setKey(key); pref.setTitle(name); pref.setSummary(apn); pref.setPersistent(false); pref.setOnPreferenceChangeListener(this); boolean selectable = ((type == null) || !type.equals("mms")); pref.setSelectable(selectable); if (selectable) { if ((mSelectedKey != null) && mSelectedKey.equals(key)) { pref.setChecked(); } apnList.addPreference(pref); } else { mmsApnList.add(pref); } cursor.moveToNext(); } cursor.close(); for (Preference preference : mmsApnList) { // 将这个preference加入到apnList中 apnList.addPreference(preference); } }
这里的ApnPreference是我们自己定义的一个类,继承于Preference。这个类很简单 就是根据R.layout.apn_preference_layout文件来对APN配置页面的每一项进行布局的。主要是两个TextView和一个RadioButton。
这里我们已经知道了进入APN设置后,系统是如何将数据库中已经存在的APN条目读取出来并通过UI的形式显示出来的。那么我们又怎么添加自己定义的APN配置信息呢?这就要用到Options Menu了,在手机上当我们按下Menu键的时候弹出一个列表,单击这个列表每一项我们可以进入相应的Activity等。
@Override public boolean onCreateOptionsMenu(Menu menu) { // 当按下Menu键的时候调用 super.onCreateOptionsMenu(menu); menu.add(0, MENU_NEW, 0, // 增加两个条目,分别用于增加APN和恢复出厂设置 getResources().getString(R.string.menu_new)) .setIcon(android.R.drawable.ic_menu_add); menu.add(0, MENU_RESTORE, 0, getResources().getString(R.string.menu_restore)) .setIcon(android.R.drawable.ic_menu_upload); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // 响应Menu按下的列表 case MENU_NEW: // 增加APN addNewApn(); return true; case MENU_RESTORE: // 恢复出厂设置 restoreDefaultApn(); return true; } return super.onOptionsItemSelected(item); } private void addNewApn() { // 启动新的Activity,动作为Intent.ACTION_INSERT startActivity(new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI)); } // 响应 设置页面每一行条目的单击事件 @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { int pos = Integer.parseInt(preference.getKey()); Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos); // 对当前选中页面进行编辑,也是启动一个Activity startActivity(new Intent(Intent.ACTION_EDIT, url)); return true; } public boolean onPreferenceChange(Preference preference, Object newValue) { Log.d(TAG, "onPreferenceChange(): Preference - " + preference + ", newValue - " + newValue + ", newValue type - " + newValue.getClass()); if (newValue instanceof String) { setSelectedApnKey((String) newValue); } return true; }
无论是增加APN还是对原有的APN条目进行编辑,我们都是通过进入一个新的Activity来完成的。下面我们找到匹配Intent.ACTION_EDIT,Intent.ACTION_INSERT
我们找到对应的Activity ApnEditor,ApnEditor也是一个继承与PreferenceActivity的类,同时实现了SharedPreferences.onSharedPreferenceChangeListener和Preference.OnPreferenceChangeListener接口。
@Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.apn_editor); sNotSet = getResources().getString(R.string.apn_not_set); mName = (EditTextPreference) findPreference("apn_name"); mApn = (EditTextPreference) findPreference("apn_apn"); mProxy = (EditTextPreference) findPreference("apn_http_proxy"); mPort = (EditTextPreference) findPreference("apn_http_port"); mUser = (EditTextPreference) findPreference("apn_user"); mServer = (EditTextPreference) findPreference("apn_server"); mPassword = (EditTextPreference) findPreference("apn_password"); mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy"); mMmsPort = (EditTextPreference) findPreference("apn_mms_port"); mMmsc = (EditTextPreference) findPreference("apn_mmsc"); mMcc = (EditTextPreference) findPreference("apn_mcc"); mMnc = (EditTextPreference) findPreference("apn_mnc"); mApnType = (EditTextPreference) findPreference("apn_type"); mAuthType = (ListPreference) findPreference(KEY_AUTH_TYPE); mAuthType.setOnPreferenceChangeListener(this); mProtocol = (ListPreference) findPreference(KEY_PROTOCOL); mProtocol.setOnPreferenceChangeListener(this); mRoamingProtocol = (ListPreference) findPreference(KEY_ROAMING_PROTOCOL); // Only enable this on CDMA phones for now, since it may cause problems on other phone // types. (This screen is not normally accessible on CDMA phones, but is useful for // testing.) TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE); if (tm.getCurrentPhoneType() == Phone.PHONE_TYPE_CDMA) { mRoamingProtocol.setOnPreferenceChangeListener(this); } else { getPreferenceScreen().removePreference(mRoamingProtocol); } mCarrierEnabled = (CheckBoxPreference) findPreference(KEY_CARRIER_ENABLED); mBearer = (ListPreference) findPreference(KEY_BEARER); mBearer.setOnPreferenceChangeListener(this); mRes = getResources(); final Intent intent = getIntent(); final String action = intent.getAction(); mFirstTime = icicle == null; if (action.equals(Intent.ACTION_EDIT)) { mUri = intent.getData(); Log.w(TAG, "llping Edit action:"+mUri.toString()); } else if (action.equals(Intent.ACTION_INSERT)) { if (mFirstTime || icicle.getInt(SAVED_POS) == 0) { mUri = getContentResolver().insert(intent.getData(), new ContentValues()); } else { mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, icicle.getInt(SAVED_POS)); } Log.w(TAG, "llping Insert action:"+mUri.toString()); mNewApn = true; // If we were unable to create a new note, then just finish // this activity. A RESULT_CANCELED will be sent back to the // original activity if they requested a result. if (mUri == null) { Log.w(TAG, "Failed to insert new telephony provider into " + getIntent().getData()); finish(); return; } // The new entry was created, so assume all will end well and // set the result to be returned. setResult(RESULT_OK, (new Intent()).setAction(mUri.toString())); } else { finish(); return; } mCursor = managedQuery(mUri, sProjection, null, null); mCursor.moveToFirst(); fillUi(); }
文章来源:http://www.itnose.net/detail/6024266.html
更多文章:http://www.itnose.net/type/85.html
相关推荐
设置android的APN配置,移动2G和联通的2G和3G网络配置,以及MMS的APN配置
Android开发之系统信息【5】——获取APN列表Android开发之系统信息【5】——获取APN列表
android 全面解析apn
android端通过代码实现apn配置,这里做一下记录,方便以后查看这部分实现内容
android APN开发流程
Android的数据连接是基于PPP方式的,主要步骤为:首先通过AT命令激活PDP连接,然后利用pppd通过数据端口完成拨号连接; 数据连接的核心控制类是DataConnectionTracker,存在于GSMPhone里,数据连接不需要用户的干预...
Android APN开发流程分析
android 设置apn,包括自动和手动,成熟代码
基于android2.2的apn开发,可以自己改写并通过第三方软件在来设置apn从而达到自己想要的结果。
Android AT命令与APN开发流程分析
在android代码中切换网络,如cmnet,cmwap
国内运营商,中国移动,联通,电信,android上网APN
NB物联网卡开卡APN参数详解,包含电信,移动,具体apn下的idle时长,tau时长,对于不同行业有不同的选择
android apn切换程序,支持最新版的安卓系统,绝对好用,下载下来收藏吧
可以将Android中APN文件转化为windowphones8中的APN文件,因为APN数量过多,所以不用手动转化,方便极了。
APN配置指北1
本文实例讲述了Android基于APN获取手机号的方法。分享给大家供大家参考。具体如下: 之前很多人说无法完全获取手机号,是因为现在有的卡不能获取,有的卡能获取,现在我们可以换一种思路来考虑问题,就是用APN的方式...
附件为apndemo,apn.xml需放到U盘或者sd卡根目录,在有信号的时候插卡或U盘3秒后配置成功
在HTC三星摩托手机均试验过,网上关于GPRS/3G开关的资源非常少,贴出来与到家一起学习,不好的地方请指正!
APN的英文全称是Access Point Name,中文全称叫接入点,是您在通过手机上网时必须配置的一个参数,它决定了您的手机通过哪种接入方式来访问网络。 有时候需要修改APN的时候会发现无法更改,连常用的海卓HIAPN都无法...