Hello, everyone. Meet again. I'm Quan Jun
Detailed explanation of APN configuration of Android system
I've been adjusting the system's native settings these days APN configuration in APK. The APN configuration option is manually added in the settings. But I still can't see it on the interface. So I followed the code. I thought it was a simple page display problem. It doesn't matter. I'll soon catch up with HAL floor (NND)
First look at settings The source code of APK is located in the packages/apps/Settings/src/com/android/settings / folder: first find the ApnSettings class. It inherits from PreferenceActivity and implements preference Onpreferencechangelistener interface. PreferencesActivity is an Activity specially used in Android to implement program setting interface and parameter storage. I won't repeat it here.
public class ApnSettings extends PreferenceActivity implements Preference.OnPreferenceChangeListener { // Restore factory set URI public static final String RESTORE_CARRIERS_URI = "content://telephony/carriers/restore"; // Normal URI. It is used for content privoder to save APN configuration information 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); // Two handles. Used to restore factory settings private RestoreApnUiHandler mRestoreApnUiHandler; private RestoreApnProcessHandler mRestoreApnProcessHandler; private String mSelectedKey; // Intent filter for multicast reception 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); // When the activity is created, the view is configured according to the xml file. // In fact, RES / XML / APN_ settings. The XML file is an empty PreferenceScreen addPreferencesFromResource(R.xml.apn_settings); getListView().setItemsCanFocus(true); // If there is a List, get the focus // This creates an Inter filter. The filtered action is ACTION_ANY_DATA_CONNECTION_STATE_CHANGED mMobileStateFilter = new IntentFilter( TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); } @Override protected void onResume() { super.onResume(); // Register a broadcast recipient registerReceiver(mMobileStateReceiver, mMobileStateFilter); if (!mRestoreDefaultApnMode) { // It is assumed that the factory settings are not restored fillList(); // Populates the ListView of the Activity } else { showDialog(DIALOG_RESTORE_DEFAULTAPN); } } }
1) First, in the onCreate() method, according to apn_settings.xml file to configure the view of the interface. It's actually a PreferenceScreen. Create an Intent filter, and the filtering action is ACTION_ANY_DATA_CONNECTION_STATE_CHANGED.
2) Then, in the onResume() method, register a broadcast recipient. When receiving the above ACTION_ANY_DATA_CONNECTION_STATE_CHANGED action. call
onReceive() method of mmobiliestatereceiver. The purpose is that when we enter the APN setting, the SIM card can be inserted to display the APN configuration information. Then infer whether it is necessary to restore the factory settings. Suppose not. Then call the fillList() method to fill in the current Activity and display the configuration information of APN.
3) First get the system property GSM sim. operator. Numeric, query the database through the ContentProvider provided by the system according to this parameter (located in the carriers table in the telephone.db database under / data / data / com.android.providers.telephone). Obtain the corresponding configuration information. Then fill it in each ApnPreference, and finally display each ApnPreference on the current PreferenceGroup.
private void fillList() { // Get the GSM of the system sim. operator. Numeric attribute String where = "numeric=\"" + android.os.SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "")+ "\""; // Call the ContentProvider provided by the system to query the database Cursor cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] { "_id", "name", "apn", "type"}, where, null, Telephony.Carriers.DEFAULT_SORT_ORDER); // Find the PreferenceGroup in the current Activity PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list"); apnList.removeAll(); ArrayList<Preference> mmsApnList = new ArrayList<Preference>(); mSelectedKey = getSelectedApnKey(); cursor.moveToFirst(); // Iterative query database 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); // Create a new ApnPreference and fill in the value of the control inside 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) { // Add this preference to apnList apnList.addPreference(preference); } }
ApnPreference here is a custom class. Inherited from Preference.
This class is very easy, which is based on r.layout apn_ preference_ Layout file to layout each item of the APN configuration page. Mainly two textviews and one RadioButton.
Here we know how the system reads the existing APN entries in the database and displays them in the form of UI after entering APN settings.
So how do we add custom APN configuration information? This requires the Options Menu. On the phone, when we press the Menu key, a list pops up. Click each item in this list to enter the corresponding Activity, etc.
@Override public boolean onCreateOptionsMenu(Menu menu) { // Called when the Menu key is pressed super.onCreateOptionsMenu(menu); menu.add(0, MENU_NEW, 0, // Add two entries for adding APN and restoring factory settings respectively 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()) { // List in response to Menu press case MENU_NEW: // Add APN addNewApn(); return true; case MENU_RESTORE: // Restore factory settings restoreDefaultApn(); return true; } return super.onOptionsItemSelected(item); } private void addNewApn() { // Start a new Activity. The action is intent ACTION_ INSERT startActivity(new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI)); } // Respond to the click event for each line entry on the setup page @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { int pos = Integer.parseInt(preference.getKey()); Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos); // Editing the currently selected page also starts an 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; }
Whether we add APN or edit the original APN entry, we complete it by entering a new Activity.
Below we find a matching intent ACTION_ EDIT. Intent.ACTION_INSERT We found the corresponding Activity ApnEditor. ApnEditor is also a class that inherits from PreferenceActivity. At the same time, SharedPreferences Onsharedpreferencechangelistener and preference Onpreferencechangelistener interface.
@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(); }
Copyright notice: original article of this blog. Blogs cannot be reproduced without permission.
Publisher: full stack programmer, stack length, please indicate the source for Reprint: https://javaforall.cn/117488.html Original link: https://javaforall.cn