Android4.0短信发送拦截(framework开发,修改)

Android中短信接收拦截比较好实现,如果要实现短信发送拦截就要修改framework的代码。

实现也不难,同时也介绍framework开发的一般步骤。


准备阶段

关于短信发送流程的详细分析网上有很多,这里简单提一下

应用层SmsManger这个类的sendTextMessage( )或sendMultipartText( )发送

通过aidl调用系统服务ISms发送短信。发送的拦截主要在系统服务里实现。


源码的工具可以参考下面博客

http://blog.csdn.net/thinkandchange/article/details/7677366


源码修改

找到framework/base/telephony/java/com/android/internal/telephony/IccSmsInterfaceManager.java

这个类就是ISms的aidl的实现,找到发送的两个方法然后将其最后一行替换为自己的方法:

    public void sendText(String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent, int priority) {
        mPhone.getContext().enforceCallingPermission(
                "android.permission.SEND_SMS",
                "Sending SMS message");
        if (Log.isLoggable("SMS", Log.VERBOSE)) {
            log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
                " text='"+ text + "' sentIntent=" +
                sentIntent + " deliveryIntent=" + deliveryIntent);
        }

        sendTextBoardcast(mContext, destAddr, scAddr, text, sentIntent, deliveryIntent,priority);
        //mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,priority);
    }
    public void sendMultipartText(String destAddr, String scAddr, List<String> parts,
            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
        mContext.enforceCallingPermission(
                "android.permission.SEND_SMS",
                "Sending SMS message");
        if (Log.isLoggable("SMS", Log.VERBOSE)) {
            int i = 0;
            for (String part : parts) {
                log("sendMultipartText: destAddr=" + destAddr + ", srAddr=" + scAddr +
                        ", part[" + (i++) + "]=" + part);
            }
        }
        sendMultipartTextBoardcast(mContext, destAddr, scAddr,(ArrayList<String>) parts,
                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
 /*       mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);*/
    }

将其发送广播出去,由其他应用决定是否拦截,为了后面还能正常发送,将所有参数发出去

    /**
      * 发送广播,通知有进程发送短信
      * @param context
      */    
        private void sendTextBoardcast(Context context,String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent, int priority) {
        Intent intent = new Intent("com.android.sms.REPORT_SMS");
        intent.putExtra("method", "sendText");
        intent.putExtra("destAddr", destAddr);
        intent.putExtra("scAddr",scAddr);
        intent.putExtra("text",text);
        intent.putExtra("sentIntent",sentIntent);
        intent.putExtra("deliveryIntent",deliveryIntent);
        intent.putExtra("priority",priority);
        int pid = Binder.getCallingPid();
        if ( pid != android.os.Process.myPid() ){
            String processName = getProcessName(context,pid);
            String packageName = getPackageName(context,processName);
            if(processName != null){
                intent.putExtra("packageName", packageName);
            } else {
                intent.putExtra("packageName", "");
            }
        } else {
            intent.putExtra("packageName", "");
        }
        context.sendBroadcast(intent);
    }
    /**
     * 发送广播,通知有进程发送多段短信
     * @param context
     */
    private void sendMultipartTextBoardcast(Context context,String destAddr, String scAddr, ArrayList<String> parts,
            ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
        Intent intent = new Intent("com.android.sms.REPORT_SMS");
        intent.putExtra("method", "sendMultipartText");
        intent.putExtra("destAddr", destAddr);
        intent.putExtra("scAddr",scAddr);
        intent.putStringArrayListExtra("parts",parts);
        intent.putParcelableArrayListExtra("sentIntents",sentIntents);
        intent.putParcelableArrayListExtra("deliveryIntents",deliveryIntents);
        int pid = Binder.getCallingPid();
        if ( pid != android.os.Process.myPid() ){
            String processName = getProcessName(context,pid);
            String packageName = getPackageName(context,processName);
            if(processName != null){
                intent.putExtra("packageName", packageName);
            } else {
                intent.putExtra("packageName", "");
            }
        } else {
            intent.putExtra("packageName", "");
        }
        context.sendBroadcast(intent);
    }

如果要知道是有哪个应用发送的,可以根据pid进程号来查找

    /**
     * 获取进程名
     * @param context
     * @param id Process ID
     * @return
     */
    public String getProcessName(Context context,int id) {
        int pid = id;
        ActivityManager mActivityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
                .getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                return appProcess.processName;
            }
        }
        return null;
    }
    /**
     * 获取包名
     * @param context
     * @param processName 进程名
     * @return
     */
    public String getPackageName(Context context,String processName){
        if(processName == null || context == null) {
            return null;
        }
        PackageManager packageManager = context.getPackageManager();
        List<ApplicationInfo> infos = packageManager.getInstalledApplications(0);
        for (ApplicationInfo info : infos) {
            if ( processName.equals(info.processName) ) {
                return info.packageName;
            } else if( processName.equals(info.packageName) ) {
                return info.packageName;
            }
        }
        return null;   
    }


既然已经拦截了发送,我们要提供另外的正常发送方法,就是之前注释的方法

    public void mySendText(String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent, int priority){
        mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent,priority);
    }
    public void mySendMultipartText(String destAddr, String scAddr, List<String> parts,
            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents){
        mDispatcher.sendMultipartText(destAddr, scAddr, (ArrayList<String>) parts,
                (ArrayList<PendingIntent>) sentIntents, (ArrayList<PendingIntent>) deliveryIntents);
    }

要使能被调用到,要在对应的aidl里添加接口

找到framework/base/telephony/java/com/android/internal/telephony/ISms.aidl

    void mySendText(in String destAddr, in String scAddr, in String text,
            in PendingIntent sentIntent, in PendingIntent deliveryIntent, in int priority);

    void mySendMultipartText(in String destinationAddress, in String scAddress,
            in List<String> parts, in List<PendingIntent> sentIntents,
            in List<PendingIntent> deliveryIntents);

最后在SmsManger里增加自己的方法

framework/base/telephony/java/android/telephony/SmsManager.java

    public void mySendText(String destAddr, String scAddr,
            String text, PendingIntent sentIntent, PendingIntent deliveryIntent, int priority){
        try {
            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
            if (iccISms != null) {
                iccISms.flySendText(destAddr, scAddr, text, sentIntent, deliveryIntent,priority);
            }
        } catch (RemoteException ex) {
            // ignore it
        }
    }
    public void mySendMultipartText(String destAddr, String scAddr, List<String> parts,
            List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents){
        try {
            ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
            if (iccISms != null) {
                iccISms.flySendMultipartText(destAddr, scAddr, parts, sentIntents, deliveryIntents);
            }
        } catch (RemoteException ex) {
            // ignore it
        }
    }

编译测试

之前先编译一遍源码

进入framework/base执行命令mm

根据打印出来的信息找到out/target/product/(芯片平台)/system/framework/framework.jar

将其adb push framework.jar system/framework

重启adb reboot


编写应用程序

广播接收器

        <span style="color:#330000;"><receiver android:name="com.interceptor.SmsReport" >
            <intent-filter>
                <action android:name="com.android.sms.REPORT_SMS" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </receiver></span>
public class SmsReport extends BroadcastReceiver {
	@Override
	public void onReceive(Context context, Intent intent) {
		
		String packageName = intent.getStringExtra("packageName");
		if(MApplication.mApp.checkSendMessages(packageName) == false){
			Toast.makeText(MApplication.mApp, packageName+"不允许发送短信", Toast.LENGTH_LONG).show();
			return;
		}
		String methodName = intent.getStringExtra("method");
		SmsManager smsManager = SmsManager.getDefault();
		if(methodName == null || "".equals(methodName)){
		    return;
		}else if(methodName.equals("sendText")){
		    String destAddr = intent.getStringExtra("destAddr");
	        String scAddr = intent.getStringExtra("scAddr");
	        String text = intent.getStringExtra("text");
	        PendingIntent sentIntent = intent.getParcelableExtra("sentIntent");
	        PendingIntent deliveryIntent = intent.getParcelableExtra("deliveryIntent");
	        int priority = intent.getIntExtra("priority", -1);
	        
	        smsManager.mySendText(destAddr, scAddr, text, sentIntent, deliveryIntent,priority);
		}else if(methodName.equals("sendMultipartText")){
		    String destAddr = intent.getStringExtra("destAddr");
                String scAddr = intent.getStringExtra("scAddr");
                ArrayList<String> parts = intent.getStringArrayListExtra("parts");
                ArrayList<PendingIntent> sentIntents = intent.getParcelableArrayListExtra("sentIntents");
                ArrayList<PendingIntent> deliveryIntents = intent.getParcelableArrayListExtra("deliveryIntents");
            
                smsManager.mySendMultipartText(destAddr, scAddr, parts, sentIntents, deliveryIntents);
		}

	}
}

要使应用程序编译通过,必须导入out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar包并且必须编译顺序比Android的jar包靠前



 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值