Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android系统APN配置具体解释

Android系统APN配置具体解释

作者头像
全栈程序员站长
发布于 2022-01-11 08:18:52
发布于 2022-01-11 08:18:52
1.5K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是全栈君

 Android 系统APN配置具体解释

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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上。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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。

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @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接口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    @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();
    }

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

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/117488.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
PreferenceActivity 的用法总结
使用addPreferencesFromResource(R.xml.preferences); 显示 xml
全栈程序员站长
2022/09/06
2380
preference用法for_notification用法
在Android3.0之前,设置界面使用PreferenceActivity,在Android3.0之后,官方推荐使用PreferenceFragment,对应于碎片化技术。
全栈程序员站长
2022/10/04
3.6K0
preference用法for_notification用法
聊聊Android应用Preference组件那点事
本文主要给大家讲述下本人使用Preference的经验和体会。为了使短信项目和系统之间的耦合度更低,使用简单,达到代码可读性更好,又要达到策划的需求,根据以上原因选择了Preference组件。
open
2020/03/19
2.6K0
聊聊Android应用Preference组件那点事
Android Settings解析
Android设置应用是Android系统中一个非常重要的系统应用,它允许用户调整和设置系统的各种参数和功能(系统设置/自定义设置/控制应用权限/开发者选项/系统信息等),使用户获得更好的使用体验。同时它一般也是Android系统开发者了解深入的第一个系统级应用,也是用户使用最频繁的系统应用。
八归少年
2023/10/23
2.1K0
Android Settings解析
安卓 topic-UI-设置 settings
应用通常包括允许用户修改应用特性和行为的设置。例如,有些应用允许用户指定是否启用通知,或指定应用与云端同步数据的频率。
acc8226
2022/05/17
3.4K0
安卓 topic-UI-设置 settings
preference 意思_Preferences
提要:PreferenceFragment展示中设置的值可以通过PreferenceManager.getDefaultSharedPreferences(context).来实现
全栈程序员站长
2022/10/04
8070
preference 意思_Preferences
Android学习笔记(十四)方便实用的首选项-PreferenceActivity
codingblock
2017/12/29
1.1K0
Android学习笔记(十四)方便实用的首选项-PreferenceActivity
数据存储之SharedPreferences
在Android系统中提供了多张存储技术,这些存储技术可以讲数据保存在各种存储介质上。例如SharedPreferences可以将数据保存在应用软件的私有存储区,这些存储区中的数据只能被写入这些数据的软件读取。除此之外,Android系统还支持文件存储、SQLite数据库、OBB文件、云存储等
小小工匠
2021/08/16
9820
Android preference_安卓fragment切换
在Android中,可以使用PreferenceActivity基类为用户显示一个用于编辑首选项的活动。
全栈程序员站长
2022/10/04
6570
Android开发(12) 无线网络和GPRS连接
概述 启用gprs连接?难道说不是自动就调用网络了么?是呀,android 会默认调用当前的活动的网络. 那么什么是活动的网络呢? 看如下代码: ConnectivityManager cm =
张云飞Vir
2020/03/16
1.8K0
android之ListPreference的用法_PreferenceActivity用法
其次,它能帮助我们方便的进行数据存储!为什么这个地方一定要强调下方便的这个词呢?原因是,我们可以根本就不使用,我们有另外的N种办法可以实现同样的功能!它的出现,相当于为我们提供了一个方便的工具,当然了,这个工具并不是必须的。
全栈程序员站长
2022/07/20
1.3K0
android之ListPreference的用法_PreferenceActivity用法
[android] 网络链接类型和渠道
2.2.1 wap的方式,中国特色,首先会连接电信运营商代理拦截10.0.0.172,HttpUrlConnection会不稳定
唯一Chat
2019/09/10
7110
009android初级篇之APP中使用系统相机相册等集成应用
这是第一种方式 在启动相机前先指定好图片的文件位置,通知intent,同时也保留在成员变量中。然后在函数中,可以直接打开该文件
上善若水.夏
2018/09/28
6910
关于PreferenceActivity的使用和一些问题的解决(自己定义Title和取值)
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/118967.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/12
5350
关于PreferenceActivity的使用和一些问题的解决(自己定义Title和取值)
Android开发笔记(一百零八)智能语音
如今越来越多的app用到了语音播报功能,例如地图导航、天气预报、文字阅读、口语训练等等。语音技术主要分两块,一块是语音转文字,即语音识别;另一块是文字转语音,即语音合成。 对中文来说,和语音播报相关的一个技术是汉字转拼音,想想看,拼音本身就是音节拼读的标记,每个音节对应一段音频,那么一句的拼音便能用一连串的音频流合成而来。汉字转拼音的说明参见《Android开发笔记(八十三)多语言支持》。 语音合成通常也简称为TTS,即TextToSpeech(从文本到语言)。语音合成技术把文字智能地转化为自然语音流,当然为了避免机械合成的呆板和停顿感,语音引擎还得对语音流进行平滑处理,确保输出的语音音律流畅、感觉自然。
aqi00
2019/01/18
5.8K1
preference用法for_interference用法
PreferenceFragment位于android.preference包下,现在推荐使用v7包下的,这里还是使用这个来说明,原理是一样的。
全栈程序员站长
2022/10/04
3.8K0
preference用法for_interference用法
偏好设置
要将可接受的值限制在 0(不包括)和 3(包括)之间,我们选择使用 PreferenceChangeListener - 它与 SharedPreferenceChangeListener 的不同之处为:
acc8226
2022/05/17
5850
Android4.42-Settings源码分析之蓝牙模块Bluetooth(上)
接着来介绍一下设置中某个模块的源码,本文依旧是基于Android4.42源码进行分析,分析一下蓝牙模块的实现。建议大致看一下关于Settings的剖析。
fanfan
2022/05/07
1.7K0
Android4.42-Settings源码分析之蓝牙模块Bluetooth(上)
语音兰度短信
原理:获取来电短信内容,调用系统的语音朗读功能。 效果图: 具体代码如下: 1,获取短信息: package com.internal.message;   import android.cont
xiangzhihong
2018/01/29
7520
语音兰度短信
安卓应用安全指南 5.5.1 处理隐私数据 示例代码
在准备应用的隐私政策时,你可以使用“协助创建应用隐私政策的工具” [29]。 这些工具以 HTML 格式和 XML 格式输出两个文件 - 应用隐私策略的摘要版本和详细版本。 这些文件的 HTML 和 XML 内容符合 MIC SPI 的建议,包括搜索标签等特性。 在下面的示例代码中,我们将演示此工具的用法,并使用由这个工具产生的 HTML 文件来展示程序隐私策略。
ApacheCN_飞龙
2022/12/01
2.2K0
推荐阅读
相关推荐
PreferenceActivity 的用法总结
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验