草庐IT

android - 拦截、阅读和取消短信

coder 2023-11-28 原文

我正在寻找一种方法来挂接 SMSManager 或较低级别的机制,以便我可以在发送任何外发 SMS 消息之前拦截、读取和取消它们。

最佳答案

迟到总比不到好:)

我已经在这上面花了 2 天...并且不想让任何其他人浪费他们的时间 :)

  1. 做一个服务,在服务类中注册一个内容观察者

更新:添加了 SMS 模型类

      public class SMS {
        public Date date;
        public String from;
        public String message;
        public String to;

        public SMS(String paramString1, String paramString2, String paramString3,Date paramDate) {
            this.from = paramString1;
            this.to = paramString2;
            this.message = paramString3;
            this.date = paramDate;
        }
     }

    public class ServiceClass extends Service implements SMSListener {
    public static boolean sendSms = true;
    private final IBinder mBinder = new LocalBinder();
    public static MyContentObserver mSMSObserver;
    private Context ctx;
    public static SMS param_SMS;
    int myID = -1;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
            // TODO Auto-generated method stub

            myID = startId;
            sendSms = true;
            Context localContext = getApplicationContext();
            ctx = localContext;

            mSMSObserver = new MyContentObserver(null);
            mSMSObserver.setSMSListener(this);
            mSMSObserver.start(localContext);

            return Service.START_STICKY;
     }

        @Override
        public void onDestroy() {
            // TODO Auto-generated method stub
            SharedPreferences prefs = getApplicationContext().getSharedPreferences(
                    "appData", 0);

            if (prefs.getBoolean(CommonStrings.KEY_PREFS_TOGGLE, false)) {

                super.onDestroy();
                Log.e("OnDestroy", "Stopping Service");
                Context localContext = getApplicationContext();
                mSMSObserver.stop(localContext);

                try {
                    stopSelf(myID);
                    Log.e("Stopping self", "Stopping Service");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public IBinder onBind(Intent intent) {
            // TODO Auto-generated method stub
            Log.e("OnBinder", "OnBinder");
            return null;
        }

        @Override
        public void reportIncomingSms(SMS paramSMS) {
            // TODO Auto-generated method stub

        }

        public void reportOutgoingSms(SMS paramSMS) {
            if (!MainActivity.stopped) {
                Log.e("OUT GOING SMS DETECTED", "OUT GOING SMS DETECTED");
                sendSms = true;
                param_SMS = paramSMS;

                // DO ANY THING, Out going Msg detected...

            }
        }

        public class LocalBinder extends Binder {
            public LocalBinder() {
            }

            public ServiceClass getService() {
                return ServiceClass.this;
            }
        }
    }
  1. 扩展内容观察器

    public class MyContentObserver extends ContentObserver {
    
    public static final int MESSAGE_TYPE_ALL = 0;
    public static final int MESSAGE_TYPE_DRAFT = 3;
    public static final int MESSAGE_TYPE_FAILED = 5;
    public static final int MESSAGE_TYPE_INBOX = 1;
    public static final int MESSAGE_TYPE_OUTBOX = 4;
    public static final int MESSAGE_TYPE_QUEUED = 6;
    public static final int MESSAGE_TYPE_SENT = 2;
    public static final String TYPE = "type";
    private SMSListener mSMSListener;
    public static long _id;
    private ContentObserver observer;
        public MyContentObserver(Handler handler) {
        super(handler);
        // TODO Auto-generated constructor stub
        }
        private void readFromOutgoingSMS(Context paramContext) {
        if (!MainActivity.stopped) {
            Cursor localCursor = paramContext.getContentResolver().query(
            Uri.parse("content://sms"), null, null, null, null);
            long l = 0;
            int i;
            if (localCursor.moveToNext()) {
                l = localCursor.getLong(localCursor.getColumnIndex("_id"));
                String str1 = localCursor.getString(localCursor
                        .getColumnIndex("protocol"));
                i = localCursor.getInt(localCursor.getColumnIndex("type"));
                if ((str1 != null) || (i != 6))
                    localCursor.close();
                    if (i == 6) {
                    int j = localCursor.getColumnIndex("body");
                    int k = localCursor.getColumnIndex("address");
                    Date localDate = new Date(localCursor.getLong(localCursor
                            .getColumnIndex("date")));
                    String str2 = localCursor.getString(k);
                    String str3 = localCursor.getString(j);
                    localCursor.close();
                        _id = l;
                      // Delete SMS and Save the sms content to custom type variable
                    if (deleteSms(paramContext, l)) {
                        SMS localSMS = new SMS("", str2, str3, localDate);
                        this.mSMSListener.reportOutgoingSms(localSMS);
                    } else {
                        localCursor.close();
                    }
                }
            }
        }
    }
    
    public static boolean deleteSms(Context paramContext, long paramLong) {
        Uri localUri = ContentUris.withAppendedId(Uri.parse("content://sms"),
                paramLong);
        boolean bool = false;
        if (localUri != null) {
            try {
                int j = paramContext.getContentResolver().delete(localUri,
                        null, null);
                if (j == 1)
                    bool = true;
                else
                    bool = false;
            } catch (Exception localException) {
                localException.printStackTrace();
                bool = false;
            }
        }
        return bool;
    }
    
    private void registerContentObserver(final Context paramContext) {
            this.observer = new ContentObserver(null) {
                    public void onChange(boolean paramAnonymousBoolean) {
                        readFromOutgoingSMS(paramContext);
                    }
                };
                paramContext.getContentResolver().registerContentObserver(
                    Uri.parse("content://sms"), true, this.observer);
            }
                public void setSMSListener(SMSListener paramSMSListener) {
                this.mSMSListener = paramSMSListener;
            }
            public void start(Context paramContext) {
                registerContentObserver(paramContext);
                listenForIncomingSms(paramContext);
            }
    
            public void stop(Context paramContext) {
                paramContext.getContentResolver().unregisterContentObserver(
                        this.observer);
            }
            private void listenForIncomingSms(Context paramContext) {
            //.....
            }
    
    }
    
  2. 短信监听器

     public abstract interface SMSListener {
     public abstract void reportIncomingSms(SMS paramSMS);
    
     public abstract void reportOutgoingSms(SMS paramSMS);
       }
    

需要的权限:

   <uses-permission android:name="android.permission.READ_SMS" />
   <uses-permission android:name="android.permission.READ_CONTACTS" />

关于android - 拦截、阅读和取消短信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5589395/

有关android - 拦截、阅读和取消短信的更多相关文章

  1. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  2. UE4 源码阅读:从引擎启动到Receive Begin Play - 2

    一、引擎主循环UE版本:4.27一、引擎主循环的位置:Launch.cpp:GuardedMain函数二、、GuardedMain函数执行逻辑:1、EnginePreInit:加载大多数模块int32ErrorLevel=EnginePreInit(CmdLine);PreInit模块加载顺序:模块加载过程:(1)注册模块中定义的UObject,同时为每个类构造一个类默认对象(CDO,记录类的默认状态,作为模板用于子类实例创建)(2)调用模块的StartUpModule方法2、FEngineLoop::Init()1、检查Engine的配置文件找出使用了哪一个GameEngine类(UGame

  3. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  4. ruby-on-rails - 如何找出拦截 'method_missing' 的内容 - 2

    使用Ruby1.8.6/Rails2.3.2我注意到在我的任何ActiveRecord模型类上调用的任何方法都返回nil而不是NoMethodError。除了烦人之外,这还破坏了动态查找器(find_by_name、find_by_id等),因为即使存在记录,它们也总是返回nil。不从ActiveRecord::Base派生的标准类不受影响。有没有办法追踪在ActiveRecord::Base之前拦截method_missing的是什么?更新:切换到1.8.7后,我发现(感谢@MichaelKohl)will_paginate插件首先处理method_missing。但是will_pa

  5. ruby-on-rails - 在 irb 中阅读文档 - 2

    我怀念ipython的一件事是它有一个?为特定功能挖掘文档的运算符。我知道ruby​​有一个类似的命令行工具,但是我在irb中调用它非常不方便。ruby/irb有类似的东西吗? 最佳答案 Pry是IPython的Ruby版本,它支持?命令来查找有关方法的文档,但语法略有不同:pry(main)>?File.dirnameFrom:file.cinRubyCore(CMethod):Numberoflines:6visibility:publicsignature:dirname()Returnsallcomponentsofthef

  6. ruby-on-rails - 取消 Rails 数据库连接 - 2

    我正在编写一个将服务器端事件与ActionController::Live结合使用的应用程序。它正在使用puma应用程序服务器。当用户连接等待来自Redis的消息时,消息Controller中的方法保持事件状态。问题是我不想通过这种方法连接到Postgres。我在六个选项卡中打开应用程序后,它有超过五个连接,由config/database.yml文件中的池大小定义,应用程序崩溃。无论如何,在调用该方法时是否可以告诉我的应用它不需要连接到数据库,因为其中没有ActiveRecord查询调用? 最佳答案 一种可能的方法是使用中间件。设

  7. ruby - 如何将 Vim 中的 "expand"文本转换成一种易于阅读的方式? - 2

    我经常使用嵌套数据结构,很多时候我必须从控制台手动分析它们。问题是它们全部打印在一行中。是否有一种简单的方法可以根据{,[,],}和逗号重新构造数据结构的显示,使其看起来像Ruby的pretty_print输出? 最佳答案 :%s/\([{,]\)/\1\r/gggVG=:setft=ruby呜呜呜 关于ruby-如何将Vim中的"expand"文本转换成一种易于阅读的方式?,我们在StackOverflow上找到一个类似的问题: https://stacko

  8. 基于SpringBoot的线上日志阅读器 - 2

    软件特点部署后能通过浏览器查看线上日志。支持Linux、Windows服务器。采用随机读取的方式,支持大文件的读取。支持实时打印新增的日志(类终端)。支持日志搜索。使用手册基本页面配置路径配置日志所在的目录,配置后按回车键生效,下拉框选择日志名称。选择日志后点击生效,即可加载日志。windows路径E:\java\project\log-view\logslinux路径/usr/local/XX历史模式历史模式下,不会读取新增的日志。针对历史文件可以分页读取,配置分页大小、跳转。历史模式下,支持根据关键词搜索。目前搜索引擎使用的是jdk自带类库,搜索速度相对较低,优点是比较简单。2G日志全文搜

  9. ruby-on-rails - 无法使用 Stripe 保存或取消订阅 - 2

    将stripe的API与RubyonRails结合使用我无法保存订阅。我能够检索、更新和保存客户对象:customer=Stripe::Customer.retrieve(some_customer_id)#thisworkscustomer.save#thisworks我还可以检索订阅:subscription=customer.subscriptions.retrieve("some_subscription_id")#这个有效但是,在尝试保存订阅时:subscription.save#这不起作用我不断得到这个:NoMethodError:undefinedmethod`save'

  10. ruby - 如何从 ruby​​ 中取消转义 c 风格的转义序列? - 2

    在ruby​​中,我如何解码c风格的转义序列?例如'\n'到换行符,'\t'到制表符? 最佳答案 好吧,如果你不喜欢eval解决方案,我已经在Ruby中破解了一个简单的状态机来正确解析字符串中的简单“\n”和“\t”,包括预转义反斜杠本身。在这里:BACKSLASH="\\"defunescape_c_string(s)state=0res=''s.each_char{|c|casestatewhen0casecwhenBACKSLASHthenstate=1elseres这个可以轻松扩展以支持更多字符,包括多字符实体,如\123。

随机推荐