Android 系统APN配置具体解释

这些天一直在调系统原生的Settings.apk里面APN配置的问题。在设置里面手动添加了APN配置选项。可是在界面上还是看不到。所以跟了下代码。原以为就是简单的页面显示的问题。这一跟不要紧。一下就快追到HAL层去了(NND).

首先看Settings.apk的源代码,位于packages/apps/Settings/src/com/android/settings/文件夹下:首先找到ApnSettings类。继承于PreferenceActivity,并实现了Preference.OnPreferenceChangeListener接口。PreferencesActivity是Android中专门用来实现程序设置界面及參数存储的一个Activity。这里就不再赘述了。

  1. public class ApnSettings extends PreferenceActivity implements
  2. Preference.OnPreferenceChangeListener {
  3.  
  4. // 恢复出厂设置的URI
  5. public static final String RESTORE_CARRIERS_URI = "content://telephony/carriers/restore";
  6. // 普通URI。用于ContentPrivoder保存着APN配置信息
  7. public static final String PREFERRED_APN_URI = "content://telephony/carriers/preferapn";
  8.  
  9. private static final Uri DEFAULTAPN_URI = Uri.parse(RESTORE_CARRIERS_URI);
  10. private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI);
  11.  
  12. // 两个句柄。用于恢复出厂设置
  13. private RestoreApnUiHandler mRestoreApnUiHandler;
  14. private RestoreApnProcessHandler mRestoreApnProcessHandler;
  15.  
  16. private String mSelectedKey;
  17.  
  18. // 组播接收的Intent过滤器
  19. private IntentFilter mMobileStateFilter;
  20.  
  21. private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() {
  22. @Override
  23. public void onReceive(Context context, Intent intent) {
  24. if (intent.getAction().equals(
  25. TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
  26. Phone.DataState state = getMobileDataState(intent);
  27. switch (state) {
  28. case CONNECTED:
  29. if (!mRestoreDefaultApnMode) {
  30. fillList();
  31. } else {
  32. showDialog(DIALOG_RESTORE_DEFAULTAPN);
  33. }
  34. break;
  35. }
  36. }
  37. }
  38. };
  39.  
  40. @Override
  41. protected void onCreate(Bundle icicle) {
  42. super.onCreate(icicle);
  43. // 在activity创建的时候依据xml文件来配置视图。
  44. // 实际上 res/xml/apn_settings.xml这个文件就是一个空的PreferenceScreen
  45. addPreferencesFromResource(R.xml.apn_settings);
  46. getListView().setItemsCanFocus(true); // 假设有List则获得焦点
  47. // 这个创建一个Inter 过滤器。过滤的动作为 ACTION_ANY_DATA_CONNECTION_STATE_CHANGED
  48. mMobileStateFilter = new IntentFilter(
  49. TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
  50. }
  51.  
  52. @Override
  53. protected void onResume() {
  54. super.onResume();
  55. // 注冊一个广播接受者
  56. registerReceiver(mMobileStateReceiver, mMobileStateFilter);
  57. if (!mRestoreDefaultApnMode) { // 假设不是恢复出厂设置
  58. fillList(); // 填充Activity的ListView
  59. } else {
  60. showDialog(DIALOG_RESTORE_DEFAULTAPN);
  61. }
  62. }
  63. }

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上。

  1. private void fillList() {
  2. // 获取系统的gsm.sim.operator.numeric 属性
  3. String where = "numeric=\"" + android.os.SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "")+ "\"";
  4.  
  5. // 调用系统提供的ContentProvider查询数据库
  6. Cursor cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] {
  7. "_id", "name", "apn", "type"}, where, null,
  8. Telephony.Carriers.DEFAULT_SORT_ORDER);
  9. // 找到当前Activity中的PreferenceGroup
  10. PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list");
  11. apnList.removeAll();
  12.  
  13. ArrayList<Preference> mmsApnList = new ArrayList<Preference>();
  14.  
  15. mSelectedKey = getSelectedApnKey();
  16. cursor.moveToFirst();
  17. // 迭代查询数据库
  18. while (!cursor.isAfterLast()) {
  19. String name = cursor.getString(NAME_INDEX);
  20. String apn = cursor.getString(APN_INDEX);
  21. String key = cursor.getString(ID_INDEX);
  22. String type = cursor.getString(TYPES_INDEX);
  23. // 新建一个 ApnPreference,填充里面控件的值
  24. ApnPreference pref = new ApnPreference(this);
  25.  
  26. pref.setKey(key);
  27. pref.setTitle(name);
  28. pref.setSummary(apn);
  29. pref.setPersistent(false);
  30. pref.setOnPreferenceChangeListener(this);
  31.  
  32. boolean selectable = ((type == null) || !type.equals("mms"));
  33. pref.setSelectable(selectable);
  34. if (selectable) {
  35. if ((mSelectedKey != null) && mSelectedKey.equals(key)) {
  36. pref.setChecked();
  37. }
  38. apnList.addPreference(pref);
  39. } else {
  40. mmsApnList.add(pref);
  41. }
  42. cursor.moveToNext();
  43. }
  44. cursor.close();
  45.  
  46. for (Preference preference : mmsApnList) { // 将这个preference增加到apnList中
  47. apnList.addPreference(preference);
  48. }
  49. }

这里的ApnPreference是我们自定义的一个类。继承于Preference。

这个类非常easy 就是依据R.layout.apn_preference_layout文件来对APN配置页面的每一项进行布局的。主要是两个TextView和一个RadioButton。

这里我们已经知道了进入APN设置后,系统是怎样将数据库中已经存在的APN条目读取出来并通过UI的形式显示出来的。

那么我们又怎么加入自定义的APN配置信息呢?这就要用到Options Menu了,在手机上当我们按下Menu键的时候弹出一个列表。单击这个列表每一项我们能够进入对应的Activity等。

  1. @Override
  2. public boolean onCreateOptionsMenu(Menu menu) { // 当按下Menu键的时候调用
  3. super.onCreateOptionsMenu(menu);
  4. menu.add(0, MENU_NEW, 0, // 添加两个条目,分别用于添加APN和恢复出厂设置
  5. getResources().getString(R.string.menu_new))
  6. .setIcon(android.R.drawable.ic_menu_add);
  7. menu.add(0, MENU_RESTORE, 0,
  8. getResources().getString(R.string.menu_restore))
  9. .setIcon(android.R.drawable.ic_menu_upload);
  10. return true;
  11. }
  12.  
  13. @Override
  14. public boolean onOptionsItemSelected(MenuItem item) {
  15. switch (item.getItemId()) { // 响应Menu按下的列表
  16. case MENU_NEW: // 添加APN
  17. addNewApn();
  18. return true;
  19.  
  20. case MENU_RESTORE: // 恢复出厂设置
  21. restoreDefaultApn();
  22. return true;
  23. }
  24. return super.onOptionsItemSelected(item);
  25. }
  26.  
  27. private void addNewApn() { // 启动新的Activity,动作为Intent.ACTION_INSERT
  28. startActivity(new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI));
  29. }
  30.  
  31. // 响应 设置页面每一行条目的单击事件
  32. @Override
  33. public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
  34. int pos = Integer.parseInt(preference.getKey());
  35. Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
  36. // 对当前选中页面进行编辑,也是启动一个Activity
  37. startActivity(new Intent(Intent.ACTION_EDIT, url));
  38. return true;
  39. }
  40.  
  41. public boolean onPreferenceChange(Preference preference, Object newValue) {
  42. Log.d(TAG, "onPreferenceChange(): Preference - " + preference
  43. + ", newValue - " + newValue + ", newValue type - "
  44. + newValue.getClass());
  45. if (newValue instanceof String) {
  46. setSelectedApnKey((String) newValue);
  47. }
  48. return true;
  49. }

不管是添加APN还是对原有的APN条目进行编辑,我们都是通过进入一个新的Activity来完毕的。

以下我们找到匹配Intent.ACTION_EDIT。Intent.ACTION_INSERT

我们找到相应的Activity ApnEditor。ApnEditor也是一个继承与PreferenceActivity的类。同一时候实现了SharedPreferences.onSharedPreferenceChangeListener和Preference.OnPreferenceChangeListener接口。

  1. @Override
  2. protected void onCreate(Bundle icicle) {
  3. super.onCreate(icicle);
  4.  
  5. addPreferencesFromResource(R.xml.apn_editor);
  6.  
  7. sNotSet = getResources().getString(R.string.apn_not_set);
  8. mName = (EditTextPreference) findPreference("apn_name");
  9. mApn = (EditTextPreference) findPreference("apn_apn");
  10. mProxy = (EditTextPreference) findPreference("apn_http_proxy");
  11. mPort = (EditTextPreference) findPreference("apn_http_port");
  12. mUser = (EditTextPreference) findPreference("apn_user");
  13. mServer = (EditTextPreference) findPreference("apn_server");
  14. mPassword = (EditTextPreference) findPreference("apn_password");
  15. mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
  16. mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
  17. mMmsc = (EditTextPreference) findPreference("apn_mmsc");
  18. mMcc = (EditTextPreference) findPreference("apn_mcc");
  19. mMnc = (EditTextPreference) findPreference("apn_mnc");
  20. mApnType = (EditTextPreference) findPreference("apn_type");
  21.  
  22. mAuthType = (ListPreference) findPreference(KEY_AUTH_TYPE);
  23. mAuthType.setOnPreferenceChangeListener(this);
  24.  
  25. mProtocol = (ListPreference) findPreference(KEY_PROTOCOL);
  26. mProtocol.setOnPreferenceChangeListener(this);
  27.  
  28. mRoamingProtocol = (ListPreference) findPreference(KEY_ROAMING_PROTOCOL);
  29. // Only enable this on CDMA phones for now, since it may cause problems on other phone
  30. // types. (This screen is not normally accessible on CDMA phones, but is useful for
  31. // testing.)
  32. TelephonyManager tm = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
  33. if (tm.getCurrentPhoneType() == Phone.PHONE_TYPE_CDMA) {
  34. mRoamingProtocol.setOnPreferenceChangeListener(this);
  35. } else {
  36. getPreferenceScreen().removePreference(mRoamingProtocol);
  37. }
  38.  
  39. mCarrierEnabled = (CheckBoxPreference) findPreference(KEY_CARRIER_ENABLED);
  40.  
  41. mBearer = (ListPreference) findPreference(KEY_BEARER);
  42. mBearer.setOnPreferenceChangeListener(this);
  43.  
  44. mRes = getResources();
  45.  
  46. final Intent intent = getIntent();
  47. final String action = intent.getAction();
  48.  
  49. mFirstTime = icicle == null;
  50.  
  51. if (action.equals(Intent.ACTION_EDIT)) {
  52. mUri = intent.getData();
  53. Log.w(TAG, "llping Edit action:"+mUri.toString());
  54. } else if (action.equals(Intent.ACTION_INSERT)) {
  55. if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
  56. mUri = getContentResolver().insert(intent.getData(), new ContentValues());
  57. } else {
  58. mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
  59. icicle.getInt(SAVED_POS));
  60. }
  61. Log.w(TAG, "llping Insert action:"+mUri.toString());
  62. mNewApn = true;
  63. // If we were unable to create a new note, then just finish
  64. // this activity. A RESULT_CANCELED will be sent back to the
  65. // original activity if they requested a result.
  66. if (mUri == null) {
  67. Log.w(TAG, "Failed to insert new telephony provider into "
  68. + getIntent().getData());
  69. finish();
  70. return;
  71. }
  72.  
  73. // The new entry was created, so assume all will end well and
  74. // set the result to be returned.
  75. setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
  76.  
  77. } else {
  78. finish();
  79. return;
  80. }
  81.  
  82. mCursor = managedQuery(mUri, sProjection, null, null);
  83. mCursor.moveToFirst();
  84.  
  85. fillUi();
  86. }

版权声明:本文博客原创文章。博客,未经同意,不得转载。

Android系统APN配置具体解释的更多相关文章

  1. Android系统定制——Download Android System 及加载system镜像文件

    定制android系统(配置及相关系统的镜像文件),具体可参考:Driver_All_in_One_V1.0——MT6735_6753.pdf文档,特别需要理解的是Download部分. 与之对应的软 ...

  2. Android系统固件定制方式

    target_product.mkAndroid系统在构建关于某种产品的固件时,一般会根据特定于该产品的具体target_product.mk来配置生成整个Android系统./target_prod ...

  3. Android Google Map v2具体解释:开发环境配置

    Android Google Map v2具体解释:开发环境配置                                       --转载请注明出处:coder-pig 说在前面: 说到地 ...

  4. 在Mac系统上配置Android真机调试环境

    在Mac系统上配置Android真机调试环境 mac上配置安卓环境还说挺方便的,真机调试也比win上要好一些.win上被各种软件强行安装了xxx助手. 在mac上就了一个干净的感觉. 下载Androi ...

  5. Android中实现全屏、无标题栏的两种办法(另附Android系统自带样式的解释)

    在进行UI设计时,我们经常需要将屏幕设置成无标题栏或者全屏.要实现起来也非常简单,主要有两种方法:配置xml文件和编写代码设置. 1.在xml文件中进行配置 在项目的清单文件AndroidManife ...

  6. Mac系统cocos2dx + android 开发环境配置

    Mac系统cocos2dx + android 开发环境配置 /****************************************************** 这遍文章主要转载自:htt ...

  7. Android APN配置

    APN概念 APN(Access Point Name),即“接入点名称”,用来标识GPRS的业务种类,目前分为两大类:CMWAP(通过GPRS访问WAP业务).CMNET(除了WAP以外的服务目前都 ...

  8. crt转cer ,6.0以上的android系统证书请求配置

    1.在服务器人员,给你发送的crt证书后,进到证书路径,执行下面语句  openssl x509 -in 你的证书.crt -out 你的证书.cer -outform der 这样你就可以得到cer ...

  9. Linux 桌面系统字体配置要略

    字体显示效果测试 这一段是为了测试宋体字的显示效果,包括宋体里面自带的英文字体,“This is english,how does it look like?”.这一行是小字.后面几个字是加粗的宋体. ...

随机推荐

  1. 用xml建立仓库的逻辑层的操作

    package com.repositoryclient.xml; import java.io.FileNotFoundException; import java.io.FileOutputStr ...

  2. struts(三)——struts框架实现登录示例

    前两篇讲解了struts框架的基本实现,自己感觉讲的也有些枯燥,今天拿登录的例子来做一个实现. 1.新建一个javaweb项目,并将struts的jar包拷贝到WebRoot/WEB-INF/lib下 ...

  3. 重写equals()与hashCode()方法

    出自:http://blog.csdn.net/renfufei/article/details/16339351 Java语言是完全面向对象的,在java中,所有的对象都是继承于Object类.Oj ...

  4. 配置JVM内存 查看内存工具

    一.配置JVM内存 1.配置JVM内存的參数有四个: -XmxJavaHeap最大值.默认值为物理内存的1/4.最佳设值应该视物理内存大小及计算机内其它内存开销而定. -XmsJavaHeap初始值, ...

  5. Wake-On-LAN待机或休眠模式中唤醒

    Wake-On-LAN简称WOL,是一种电源管理功能:如果存在网络活动,则允许设备将操作系统从待机或休眠模式中唤醒.许多主板厂商支持IBM提出的网络唤醒标准.该标准允许网络管理员远程打开PC机电源,以 ...

  6. 基于MVC3下拉列表联动(JQuery)

    上次项目中遇到一个需要多个下拉列表联动的操作,今天有空将实现方式整理以便以后参考. 要达到的效果是,点击一个下拉框,则另一个下拉框的值发生对应变化.如:选择中国,则另个一下拉框里显示中国各个省份. 传 ...

  7. Codeforces Round #256 (Div. 2) C. Painting Fence 或搜索DP

    C. Painting Fence time limit per test 1 second memory limit per test 512 megabytes input standard in ...

  8. .net Work Flow 4.0

    工作流 依据 WfMC 的定义.工作流(WorkFlow)就是自己主动运作的业务过程部分或总体.表现为參与者对文件.信息或任务依照规程採取行动,并令其在參与者之间传递.官方的总是非常抽象,抽象是为了可 ...

  9. SAP ABAP计划 SY-REPID与SY-CPROG差异

    首先,它的两个解释   sy-repid is the name of the current program.  "当前程序的程序名                             ...

  10. 算法战斗:给定一个号码与通配符问号W,问号代表一个随机数字。 给定的整数,得到X,和W它具有相同的长度。 问:多少整数协议W的形式和的比率X大?

    如果说: 给定一个号码与通配符问号W,问号代表一个随机数字. 给定的整数,得到X,和W它具有相同的长度. 问:多少整数协议W的形式和的比率X大? 进格公式 数据的多组,两排各数据的,W,第二行是X.它 ...