AndroidシステムAPN構成の詳細

13484 ワード


ここ数日ずっとシステムの原生を調整しています.アプリ内のAPN構成の問題は、設定中に手動でAPN構成オプションを追加しましたが、インタフェースではまだ見えません.だからコードについて、简単なページ表示の问题だと思っていたが、このフォローは大丈夫で、すぐにHAL层に追いついた(NND).
まず見て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構成ページの各項目をレイアウトします.主に2つのTextViewと1つの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を実現しました.SharedPreferenceChangeListenerと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