package
com.ssal;
import
java.io.ByteArrayInputStream;
import
java.io.ByteArrayOutputStream;
import
java.io.ObjectInputStream;
import
java.io.ObjectOutputStream;
public
class
Snippet
{
public static void main(String[] args) throws
Exception
{
Integer a =
new
Integer(1);
ByteArrayOutputStream buf =
new
ByteArrayOutputStream();
ObjectOutputStream o =
new
ObjectOutputStream(buf);
o.writeObject(a);
// Now get copies:
ObjectInputStream in =
new ObjectInputStream(new
ByteArrayInputStream(buf.toByteArray()));
Integer b = (Integer) in.readObject();
System.
out
.println(a);
a = 12;
System.
out
.println(b);
这里以MTK4.0代码为基础进行分析。
首先是Contacts.apk
拨号盘是依附于DialpadFragment上的。查看源码可以发现。无论是普通拨号还是视频拨号都会调用如下方法
protected void dialButtonPressedInner(String number, int type) { if (TextUtils.isEmpty(number)) { / .....} ...... final Intent intent = newDialNumberIntent(number, type); if (getActivity() instanceof DialtactsActivity) { intent.putExtra(DialtactsActivity.EXTRA_CALL_ORIGIN, DialtactsActivity.CALL_ORIGIN_DIALTACTS); } mCallOptionHandler.startActivity(intent); }
其中
private Intent newDialNumberIntent(String number, int type) { final Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, Uri.fromParts("tel", number, null)); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); if((type & DIAL_NUMBER_INTENT_IP) != 0) intent.putExtra(Constants.EXTRA_IS_IP_DIAL, true); if((type & DIAL_NUMBER_INTENT_VIDEO) != 0) intent.putExtra(Constants.EXTRA_IS_VIDEO_CALL, true); return intent; }
会加入Intent.ACTION_CALL_PRIVILEGED,Uri.fromParts("tel", number, null)和是否是VIDEO_CALL / IP_CALL的Extra.调用CallOptionHandler的StartActivity方法
public void startActivity(Intent intent) { ....... if(PhoneNumberUtils.isEmergencyNumber(mNumber) || intent.getIntExtra(Constants.EXTRA_SLOT_ID, -1) != -1) { final Intent broadcastIntent = newCallBroadcastIntent(mNumber, CallOptionHelper.DIAL_TYPE_VOICE, 0); mContext.sendBroadcast(broadcastIntent); return; } mCallOptionHelper.makeCall(intent); } else { intent.setClassName(Constants.PHONE_PACKAGE, Constants.OUTGOING_CALL_BROADCASTER); mContext.startActivity(intent); } Profiler.trace(Profiler.CallOptionHandlerLeaveStartActivity); }
这里会判断是否是紧急拨号。如果是紧急拨号则调用 newCallBroadcastIntent返回的Intent发送广播。不是则CallOptionHandler.makeCall
public void makeCall(Intent intent) { int type = DIAL_TYPE_VOICE; if(intent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false)) type = DIAL_TYPE_VIDEO; final Uri uri = intent.getData(); final String scheme = uri.getScheme(); if(scheme.equals("sip") && !followSimSetting) type = DIAL_TYPE_SIP; if(Constants.VOICEMAIL_URI.equals(intent.getData().toString())) type = DIAL_TYPE_VOICE; ...... makeCall(number, type, originalSim); }
这里又将Type类型分为3种 DIAL_TYPE_VOICE,DIAL_TYPE_VIDEO,DIAL_TYPE_SIP
protected void makeCall(String number, int type, long originalSim) { .... switch(type) { case DIAL_TYPE_SIP: ..... break; case DIAL_TYPE_VIDEO:{ ..... break; case DIAL_TYPE_VOICE: makeVoiceCall(number, type, originalSim, callbackArgs); break; } mCallback.onMakeCall(callbackArgs); }
这里会根据type的类型去实现CallbackArgs callbackArgs对象的不同属性。其中这3种type会存放在callbackArgs.type属性中。然后调用mCallback.onMakeCall方法。查找可以知道onMakeCall是在CallOptionHandler里面实现的。
public void onMakeCall(final CallbackArgs args) { int slot = -1; switch (args.reason) { case CallOptionHelper.MAKE_CALL_REASON_OK: { if(args.type == CallOptionHelper.DIAL_TYPE_VOICE){ //获取slot } if(args.type == ...){ //获取slot } mIntent.putExtra(Constants.EXTRA_SLOT_ID, slot); .... afterCheckSIMStatus(com.mediatek.CellConnService.CellConnMgr.RESULT_STATE_NORMAL, slot); .... break; case MAKE_CALL_REASON_3G_SERVICE_OFF: ..... .... } } }
这里的mIntent为CallOptionHAndler.startActivity中的intent,在onMakeCall方法中加入了slot字段。然后调用afterCheckSIMStatus方法。
【笔者这里理解的slot字段是一个标志电话类型的标志位。如果slot =1 则是一般电话,slot = 0则是紧急拨号,slot<0则是没有插入SIM卡,不知道正确与否。】
private boolean afterCheckSIMStatus(int result, int slot) { ... // ip dial only support voice call boolean noSim = SIMInfoWrapper.getDefault().getInsertedSimCount() == 0; if(!mIntent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false) && mIntent.getBooleanExtra(Constants.EXTRA_IS_IP_DIAL, false) && !noSim) { .. } } // a little tricky here, check the voice mail number if(Constants.VOICEMAIL_URI.equals(mIntent.getData().toString())) { //VoiceMailNumber .. } } String number = getInitialNumber(mIntent); final int type = mIntent.getBooleanExtra(Constants.EXTRA_IS_VIDEO_CALL, false) ? CallOptionHelper.DIAL_TYPE_VIDEO : CallOptionHelper.DIAL_TYPE_VOICE; final Intent broadcastIntent = newCallBroadcastIntent(number, type, slot); mContext.sendBroadcast(broadcastIntent); return true; }
这里最后将调用newCallBroadcastIntent。我们发现紧急拨号或者其他的拨号,如果拨号成功,都是使用newCallBroadcastIntent返回的Intent来发送广播。
private Intent newCallBroadcastIntent(String number, int type, int slot) { Intent intent = new Intent(OUTGOING_CALL_RECEIVER); intent.setClassName(PACKAGE, OUTGOING_CALL_RECEIVER); if(type == CallOptionHelper.DIAL_TYPE_VIDEO) intent.putExtra(Constants.EXTRA_IS_VIDEO_CALL, true); if(type == CallOptionHelper.DIAL_TYPE_SIP) intent.setData(Uri.fromParts("sip", number, null)); else intent.setData(Uri.fromParts("tel", number, null)); intent.putExtra(Constants.EXTRA_SLOT_ID, slot); return intent; }
到这里会发现,最后发送出去的intent只会包含2个有用的信息。就是Uri和Constants.EXTRA_SLOT_ID。最后该广播将在Phone.apk中的OutgoingCallReceiver中截获。
SmsManager manager = SmsManager.getDefault();
ArrayList<String> texts = manager.divideMessage(content);
for(String text : texts){
manager.sendTextMessage(number, null, text, null, null);
}
在manifest.xml文件中,添加权限
<uses-permission android:name="android.permission.SEND_SMS"/>