本文共 14096 字,大约阅读时间需要 46 分钟。
相关控件初始化方法:showSmscPref
private void showSmscPref () {getString(R.string.pref_one_smcs)
: getString(R.string.pref_more_smcs, i + 1); pref.setTitle(title); pref.setOnPreferenceClickListener(new OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { MyEditDialogFragment dialog = MyEditDialogFragment.newInstance( MessagingPreferenceActivity.this, preference.getTitle(), preference.getSummary(), Integer.valueOf(preference.getKey())); dialog.show(getFragmentManager(), "dialog"); return true; } }); mSmscPrefCate.addPreference(pref); mSmscPrefList.add(pref); updateSMSCPref(i, airplaneModeOn); } registerReceiver();}
这里使用了一个内部类MyEditDialogFragment,该类继承了DialogFragment。
public static class MyEditDialogFragment extends DialogFragment {
private MessagingPreferenceActivity mActivity; public static MyEditDialogFragment newInstance(MessagingPreferenceActivity activity, CharSequence title, CharSequence smsc, int sub) { MyEditDialogFragment dialog = new MyEditDialogFragment(); dialog.mActivity = activity; Bundle args = new Bundle(); args.putCharSequence(TITLE, title); args.putCharSequence(SMSC, smsc); args.putInt(SUB, sub); dialog.setArguments(args); return dialog; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final int sub = getArguments().getInt(SUB); if (null == mActivity) { mActivity = (MessagingPreferenceActivity) getActivity(); dismiss(); } final EditText edit = new EditText(mActivity); edit.setPadding(15, 15, 15, 15); edit.setText(getArguments().getCharSequence(SMSC)); Dialog alert = new AlertDialog.Builder(mActivity) .setTitle(getArguments().getCharSequence(TITLE)) .setView(edit) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { MyAlertDialogFragment newFragment = MyAlertDialogFragment.newInstance( mActivity, sub, edit.getText().toString()); newFragment.show(getFragmentManager(), "dialog"); dismiss(); } }) .setNegativeButton(android.R.string.cancel, null) .setCancelable(true) .create(); alert.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); return alert; } }上述代码调用了还有一个内部类:《TAG 1-2》public static class MyAlertDialogFragment extends DialogFragment {
private MessagingPreferenceActivity mActivity; public static MyAlertDialogFragment newInstance(MessagingPreferenceActivity activity, int sub, String smsc) { MyAlertDialogFragment dialog = new MyAlertDialogFragment(); dialog.mActivity = activity; Bundle args = new Bundle(); args.putInt(SUB, sub); args.putString(SMSC, smsc); dialog.setArguments(args); return dialog; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final int sub = getArguments().getInt(SUB); final String displayedSMSC = getArguments().getString(SMSC); // When framework re-instantiate this fragment by public empty // constructor and call onCreateDialog(Bundle savedInstanceState) , // we should make sure mActivity not null. if (null == mActivity) { mActivity = (MessagingPreferenceActivity) getActivity(); } return new AlertDialog.Builder(mActivity) .setIcon(android.R.drawable.ic_dialog_alert).setMessage( R.string.set_smsc_confirm_message) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.phonefeature", "com.android.phonefeature.smsc.SmscService")); intent.setAction(COMMAND_SET_SMSC); intent.putExtra(SUB, sub); intent.putExtra(SMSC, displayedSMSC); mActivity.startService(intent); } }) .setNegativeButton(android.R.string.cancel, null) .setCancelable(true) .create(); } }当用户点击确认(OK)后,会启动一个SmscService服务,而且把改动后的smsc number封装到intent中去,在SmscService服务中的onStartCommand将Intent中的数加入到消息队列中进行处理。 public int onStartCommand(Intent intent, int flags, int startId) { int sub = intent.getIntExtra(SUB, 0); int count = MSimTelephonyManager.getDefault().getPhoneCount(); Phone phone = count > 1 ? MSimPhoneFactory.getPhone(sub) : PhoneFactory.getDefaultPhone(); if (phone == null) return START_STICKY; boolean enable = phone.getIccCard().hasIccCard(); Intent i = new Intent(); i.setAction(NOTIFY_PHONE_STATE); i.putExtra(SUB, sub); i.putExtra(ENABLE, enable); sendBroadcast(i); String action = intent.getAction(); Message msg; if (COMMAND_GET_SMSC.equals(action)) { msg = mHandler.obtainMessage(MSG_GET_SMSC); msg.arg1 = sub; phone.getSmscAddress(msg); } else if (COMMAND_SET_SMSC.equals(action)) { msg = mHandler.obtainMessage(MSG_SET_SMSC); msg.arg1 = sub; String displayedSMSC = intent.getStringExtra(SMSC); Bundle bundle = new Bundle(); bundle.putString(SMSC, displayedSMSC); msg.setData(bundle); String actualSMSC = adjustSMSC(displayedSMSC); phone.setSmscAddress(actualSMSC, msg); } return START_STICKY; }上述代码中的phone。通过验证分析,得到phone为GSMPhone的实例,验证的代码为PhoneFactory类中的makeDefaultPhone方法进行验证得到(我这里验证的结果为GSM:
public static void makeDefaultPhone(Context context) {<TAG 1-1>
synchronized(Phone.class) { if (!sMadeDefaults) { sLooper = Looper.myLooper(); sContext = context; if (sLooper == null) { throw new RuntimeException( "PhoneFactory.makeDefaultPhone must be called from Looper thread"); } int retryCount = 0; for(;;) { boolean hasException = false; retryCount ++; try { // use UNIX domain socket to // prevent subsequent initialization new LocalServerSocket("com.android.internal.telephony"); } catch (java.io.IOException ex) { hasException = true; } if ( !hasException ) { break; } else if (retryCount > SOCKET_OPEN_MAX_RETRY) { throw new RuntimeException("PhoneFactory probably already running"); } else { try { Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); } catch (InterruptedException er) { } } } sPhoneNotifier = new DefaultPhoneNotifier(); // Get preferred network mode int preferredNetworkMode = RILConstants.PREFERRED_NETWORK_MODE; if (TelephonyManager.getLteOnCdmaModeStatic() == PhoneConstants.LTE_ON_CDMA_TRUE) { preferredNetworkMode = Phone.NT_MODE_GLOBAL; } int networkMode = Settings.Global.getInt(context.getContentResolver(), Settings.Global.PREFERRED_NETWORK_MODE, preferredNetworkMode); Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkMode)); // As per certain operator requirement, the device is expected to be in global《TAG 1-2》 // mode from boot up, by enabling the property persist.env.phone.global the // network mode is set to global during boot up. if (SystemProperties.getBoolean("persist.env.phone.global", false)) { networkMode = Phone.NT_MODE_LTE_CMDA_EVDO_GSM_WCDMA; Settings.Global.putInt(context.getContentResolver(), Settings.Global.PREFERRED_NETWORK_MODE, networkMode); } // Get cdmaSubscription mode from Settings.Global int cdmaSubscription; cdmaSubscription = Settings.Global.getInt(context.getContentResolver(), Settings.Global.CDMA_SUBSCRIPTION_MODE, sPreferredCdmaSubscription); Rlog.i(LOG_TAG, "Cdma Subscription set to " + cdmaSubscription); //reads the system properties and makes commandsinterface sCommandsInterface = new RIL(context, networkMode, cdmaSubscription); // Instantiate UiccController so that all other classes can just call getInstance() UiccController.make(context, sCommandsInterface); int phoneType = TelephonyManager.getPhoneType(networkMode); if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { Rlog.i(LOG_TAG, "Creating GSMPhone"); sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier)); android.util.Log.d("bill","GSM"); } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { switch (TelephonyManager.getLteOnCdmaModeStatic()) { case PhoneConstants.LTE_ON_CDMA_TRUE: Rlog.i(LOG_TAG, "Creating CDMALTEPhone"); sProxyPhone = new PhoneProxy(new CDMALTEPhone(context, sCommandsInterface, sPhoneNotifier)); android.util.Log.d("bill","CDMALTE"); break; case PhoneConstants.LTE_ON_CDMA_FALSE: default: Rlog.i(LOG_TAG, "Creating CDMAPhone"); sProxyPhone = new PhoneProxy(new CDMAPhone(context, sCommandsInterface, sPhoneNotifier)); android.util.Log.d("bill","CDMA"); break; } } sMadeDefaults = true; } } } 可是GSMPhone中并没有setSmscAddress()方法,可是GSMPhone继承了BasePhone类,因此我们在BasePhone中找到了setSmscAddress()方法。 @Override public void setSmscAddress(String address, Message result) { mCi.setSmscAddress(address, result); }上述代码中的mCi为接口CommandsInterface的实例。mCi的所引用的实例为BasePhone构造函数中传递过来的,因此我们代码<TAG1-1>中找到了该实例为RIL的实例。因此我们在RIL类中找到了setSmscAddress方法;
@Override
public void setSmscAddress(String address, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_SMSC_ADDRESS, result); rr.mParcel.writeString(address); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " : " + address); send(rr); }private void send(RILRequest rr) {
Message msg; if (mSocket == null) { rr.onError(RADIO_NOT_AVAILABLE, null); rr.release(); return; } msg = mSender.obtainMessage(EVENT_SEND, rr); acquireWakeLock(); msg.sendToTarget(); }在上述代码中send()方法会发消息给RIL中RILSender进行处理,同一时候msg中封装了MSG_SET_SMSC,在RIL的RILSender中运行写卡操作,同一时候发消息给SmscService。
//***** Handler implementation
@Override public void handleMessage(Message msg) { RILRequest rr = (RILRequest)(msg.obj); RILRequest req = null; switch (msg.what) { case EVENT_SEND: /** * mRequestMessagePending++ already happened for every * EVENT_SEND, thus we must make sure * mRequestMessagePending-- happens once and only once */ boolean alreadySubtracted = false; try { LocalSocket s; s = mSocket; if (s == null) { rr.onError(RADIO_NOT_AVAILABLE, null); rr.release(); if (mRequestMessagesPending > 0) mRequestMessagesPending--; alreadySubtracted = true; return; } synchronized (mRequestList) { mRequestList.add(rr); mRequestMessagesWaiting++; } if (mRequestMessagesPending > 0) mRequestMessagesPending--; alreadySubtracted = true; byte[] data; data = rr.mParcel.marshall(); rr.mParcel.recycle(); rr.mParcel = null; if (data.length > RIL_MAX_COMMAND_BYTES) { throw new RuntimeException( "Parcel larger than max bytes allowed! " + data.length); } // parcel length in big endian dataLength[0] = dataLength[1] = 0; dataLength[2] = (byte)((data.length >> 8) & 0xff); dataLength[3] = (byte)((data.length) & 0xff); //Rlog.v(RILJ_LOG_TAG, "writing packet: " + data.length + " bytes"); s.getOutputStream().write(dataLength); s.getOutputStream().write(data); } catch (IOException ex) { Rlog.e(RILJ_LOG_TAG, "IOException", ex); req = findAndRemoveRequestFromList(rr.mSerial); // make sure this request has not already been handled, // eg, if RILReceiver cleared the list. if (req != null || !alreadySubtracted) { rr.onError(RADIO_NOT_AVAILABLE, null); rr.release(); } } catch (RuntimeException exc) { Rlog.e(RILJ_LOG_TAG, "Uncaught exception ", exc); req = findAndRemoveRequestFromList(rr.mSerial); // make sure this request has not already been handled, // eg, if RILReceiver cleared the list. if (req != null || !alreadySubtracted) { rr.onError(GENERIC_FAILURE, null); rr.release(); } } finally { // Note: We are "Done" only if there are no outstanding // requests or replies. Thus this code path will only release // the wake lock on errors. releaseWakeLockIfDone(); } if (!alreadySubtracted && mRequestMessagesPending > 0) { mRequestMessagesPending--; } break;这里进行推断写卡操作是否成功,并发送广播。
private Handler mHandler = new Handler() {
@Override public void handleMessage(Message msg) { AsyncResult ar = (AsyncResult) msg.obj; String smsc = null; switch (msg.what) { case MSG_SET_SMSC: if (ar.exception != null) { notifyChange(NOTIFY_SMSC_ERROR, null, 0); return; } else { Bundle bundle = msg.getData(); smsc = bundle.getString(SMSC); notifyChange(NOTIFY_SMSC_SUCCESS, null, 0); } break;private void notifyChange(String notify, String smsc, int sub) {
Intent intent = new Intent(notify); intent.putExtra(SMSC, smsc); intent.putExtra(SUB, sub); sendBroadcast(intent); }我们在MessagingPreferenceActivity的registerReceiver()方法中注冊广播接收器进行监听。
private void registerReceiver() {
if (mReceiver != null) return; mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) { /*AddBy:yabin.huang BugID:SWBUG00029352 Date:20140521*/ updateSMSCPref(ALL_SUB, isAirplaneModeOn()); Message msg = new Message(); msg.what = AIR_PLANE_MODE_CHANGED; msg.arg1 = (isAirplaneModeOn() ?AIR_PLANE_MODE_ENABLE : AIR_PLANE_MODE_DISABLE);
mAirPlaneModeHandler.sendMessage(msg); } else if(TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(action)){ if(isSimReady()) updateSMSCPref(ALL_SUB, isAirplaneModeOn()); } else if (NOTIFY_SMSC_ERROR.equals(action)) { showToast(R.string.set_smsc_error); } else if (NOTIFY_SMSC_SUCCESS.equals(action)) { showToast(R.string.set_smsc_success); int sub = intent.getIntExtra(SUB, 0); String summary = intent.getStringExtra(SMSC); Log.d("bill","summary--"+summary); mSmscPrefList.get(sub).setSummary(summary); } else if (NOTIFY_SMSC_UPDATE.equals(action)) { int sub = intent.getIntExtra(SUB, 0); if(TextUtils.isEmpty(mSmscPrefList.get(sub).getSummary())){ String summary = intent.getStringExtra(SMSC); if(summary==null||summary.length()==0){ updateSMSCPref(ALL_SUB, isAirplaneModeOn()); mSmscPrefList.get(sub).setEnabled(false); mSmscPrefList.get(sub).setSummary(null); }else{ mSmscPrefList.get(sub).setEnabled(true); mSmscPrefList.get(sub).setSummary(summary); } }else{ mSmscPrefList.get(sub).setEnabled(true); } } } }; IntentFilter filter = new IntentFilter(); filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); filter.addAction(NOTIFY_SMSC_ERROR); filter.addAction(NOTIFY_SMSC_SUCCESS); filter.addAction(NOTIFY_SMSC_UPDATE); registerReceiver(mReceiver, filter); } 至今。改变整个过程的短信中心号码被整理完毕。版权声明:本文博客原创文章,博客,未经同意,不得转载。
本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/4680325.html,如需转载请自行联系原作者