Android 6.0监听短信(有Git真好,简单方便+轻松愉快)

转载请注明出处:王亟亟的大牛之路

最近在最后的任职期还被榨了一顿忙的飞起,不过今天是最后一天了,帮着处理个BUG就功德圆满了。然后最近在做一个手机间通信+XX监听的Demo,其中一部分是关于短信监听的,然后正好6.0授权的一些因素,那就把这部分的实现单独拆出来做这么个Demo,顺道把这几天觉得发现的不错的第三方库贡献给大家

先来看一下运行效果

先是配置把要过滤的短信字段输入

输入框控件

 compile ‘com.github.florent37:materialtextfield:1.0.5‘

然后用一自定义RV来显示/处理输入的内容

    compile ‘com.nikhilpanju.recyclerviewenhanced:recyclerviewenhanced:1.0.0‘

然后用户输完就跳转到监听页面,当有短信了,显示如下

再来看下 项目结构

用到的库的清单


dependencies {
    compile fileTree(dir: ‘libs‘, include: [‘*.jar‘])
    testCompile ‘junit:junit:4.12‘
    compile ‘com.android.support:appcompat-v7:23.4.0‘
    compile ‘com.apkfuns.logutils:library:1.4.2‘
    compile ‘com.jakewharton:butterknife:8.1.0‘
    compile ‘com.github.navasmdc:MaterialDesign:[email protected]‘
    apt ‘com.jakewharton:butterknife-compiler:8.1.0‘
    compile ‘com.nikhilpanju.recyclerviewenhanced:recyclerviewenhanced:1.0.0‘
    compile ‘com.github.florent37:materialtextfield:1.0.5‘
    compile ‘com.lovedise:permissiongen:0.0.6‘
}

OK,来一步步读代码,先从配置开始

public class SettingActivity extends BaseActivity {
    @BindView(R.id.input)
    EditText input;
    @BindView(R.id.add)
    ButtonRectangle add;
    @BindView(R.id.jump)
    ButtonRectangle jump;
    @BindView(R.id.recyclerView)
    RecyclerView recyclerView;
    private MainAdapter mAdapter;

    private RecyclerTouchListener onTouchListener;
    //数据集合
    private List<String> list;

    @Override
    int getLayout() {
        return R.layout.activity_setting;
    }

    @Override
    void init() {
        ButterKnife.bind(this);
        list = new ArrayList<>();
        mAdapter = new MainAdapter(this, list);
        recyclerView.setAdapter(mAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        onTouchListener = new RecyclerTouchListener(this, recyclerView);
    }

    @Override
    void logic() {
        //注册滑动删除行为
        onTouchListener.setSwipeOptionViews(R.id.edit)
                .setSwipeable(R.id.rowFG, R.id.rowBG, new RecyclerTouchListener.OnSwipeOptionsClickListener() {
                    @Override
                    public void onSwipeOptionClicked(int viewID, int position) {
                        if (viewID == R.id.edit) {
                            list.remove(position);
                            mAdapter.notifyDataSetChanged();
                        }
                    }
                });
        recyclerView.addOnItemTouchListener(onTouchListener);
    }

    @Override
    void onResumeInit() {
        //刷新适配器
        if (list.size() > 0) {
            mAdapter.notifyDataSetChanged();
        }
    }

    @Override
    void onResumeLogic() {

    }

    @Override
    protected void onPause() {
        super.onPause();
        //释放无用资源
        recyclerView.removeOnItemTouchListener(onTouchListener);
    }

    @OnClick({R.id.add, R.id.jump})
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.add:
                String value = input.getText().toString().trim();
                if (!value.isEmpty()) {
                    list.add(value);
                    mAdapter.notifyDataSetChanged();
                    input.setText("");
                }
                break;
            case R.id.jump:

                if (list.size() > 0) {
                    Intent intent = new Intent(SettingActivity.this, MainActivity.class);
                    intent.putStringArrayListExtra("dataList", (ArrayList<String>) list);
                    startActivity(intent);
                } else {
                    Toast.makeText(getApplicationContext(), "请添加过滤内容", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }
}

具体重要步骤已经在注解里写着了,主要大家可以看下这个RV库,支持部分点击,全局点击和自定义滑动删除在 https://github.com/ddwhan0123/Useful-Open-Source-Android的 RV部分有收纳

再来看下主类

public class MainActivity extends BaseActivity {
    private static final String ACTION = "android.provider.Telephony.SMS_RECEIVED";
    private SMSBroadcastReceiver mSMSBroadcastReceiver;
    private List<String> intentList;
    @BindView(R.id.text)
    TextView text;

    @Override
    int getLayout() {
        return R.layout.activity_main;
    }

    @Override
    void init() {
        ButterKnife.bind(this);
        //接受传递来的过滤集合
        intentList = getIntent().getStringArrayListExtra("dataList");
    }

    @Override
    void logic() {
        //授权
        PermissionGen.with(MainActivity.this)
                .addRequestCode(100)
                .permissions(
                        Manifest.permission.RECEIVE_SMS,
                        Manifest.permission.READ_SMS)
                .request();

        //生成广播处理
        mSMSBroadcastReceiver = new SMSBroadcastReceiver();
        mSMSBroadcastReceiver.setOnReceivedMessageListener(new SMSBroadcastReceiver.MessageListener() {
            @Override
            public void onReceived(PhoneMessage phoneMessage) {
                for (int k = 0; k < intentList.size(); k++) {
                    if (phoneMessage.getMsgContent().contains(intentList.get(k))) {
                        String msg = phoneMessage.getPhoneNumber() + "*" + phoneMessage.getMsgTime() + "*" + phoneMessage.getMsgContent();
                        LogUtils.d("--->发送的对象是 " + msg);
                        text.setText(msg);
                    }
                }

            }
        });
    }

    @Override
    void onResumeInit() {

    }

    @Override
    void onResumeLogic() {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //注销广播
        if (mSMSBroadcastReceiver != null) {
            this.unregisterReceiver(mSMSBroadcastReceiver);
            mSMSBroadcastReceiver = null;
        }
    }

    @PermissionSuccess(requestCode = 100)
    public void doRegisterReceiver() {
        //实例化过滤器并设置要过滤的广播
        IntentFilter intentFilter = new IntentFilter(ACTION);
        intentFilter.setPriority(1000);
        //注册广播
        this.registerReceiver(mSMSBroadcastReceiver, intentFilter);
    }

    @PermissionFail(requestCode = 100)
    public void doFailRegisterReceiver() {
        Toast.makeText(this, "Contact permission is not granted", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                           int[] grantResults) {
        PermissionGen.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
    }
}

这个类在一开始申请读取短信的授权,然后根据授权成功与否的回调来开启广播或者弹出失败的Toast(实际生产时记得经常看看广播在不在,因为授权行为只有在装的第一次提示)

这边用的是动态注册广播,毕竟常年监视用户的行为我是拒绝的,生活所迫没办法。

public class SMSBroadcastReceiver extends BroadcastReceiver {

    private static MessageListener mMessageListener;
    public static final String SMS_RECEIVED_ACTION = "android.provider.Telephony.SMS_RECEIVED";

    public SMSBroadcastReceiver() {
        super();
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        LogUtils.d("----> SMSBroadcastReceiver onReceive");
        if (intent.getAction().equals(SMS_RECEIVED_ACTION)) {
            Object[] pdus = (Object[]) intent.getExtras().get("pdus");
            for (Object pdu : pdus) {
                SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) pdu);
                String sender = smsMessage.getDisplayOriginatingAddress();
                //短信内容
                String content = smsMessage.getDisplayMessageBody();
                long date = smsMessage.getTimestampMillis();
                Date tiemDate = new Date(date);
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String time = simpleDateFormat.format(tiemDate);
                PhoneMessage phoneMessage = new PhoneMessage();
                phoneMessage.setPhoneNumber(sender);
                phoneMessage.setMsgTime(time);
                phoneMessage.setMsgContent(content);

                mMessageListener.onReceived(phoneMessage);
                abortBroadcast();
            }
        }

    }

    //回调接口
    public interface MessageListener {
        void onReceived(PhoneMessage phoneMessage);
    }

    public void setOnReceivedMessageListener(MessageListener messageListener) {
        this.mMessageListener = messageListener;
    }

}

广播和主Activity是通过接口互相通信的,并没用Message什么的,觉得接口比较简单实现,封装了一个“消息对象”,传递着手机号/时间/具体内容

过滤的行为交给Activity做,不希望广播内部过于复杂(可以考虑改成MVP做)

源码地址:https://github.com/ddwhan0123/BlogSample/tree/master/GetSMSDemo

下载链接:https://github.com/ddwhan0123/BlogSample/blob/master/GetSMSDemo/GetSMSDemo.zip?raw=true

对了,你们谁上海的收小弟,你看收我成不成?!这不是开玩笑!(冒着被领导看到的风险)

带我的扫下面微信联系我(注明来意)

时间: 2024-11-10 13:17:32

Android 6.0监听短信(有Git真好,简单方便+轻松愉快)的相关文章

Android实战简易教程-第三十六枪(监听短信)

一般用户喜欢用手机号作为用户名注册APP账号,这时一般都是通过手机验证码的方式进行验证,下面我们就研究一个非常实用的方法,通过监听短信-实现短信验证码的自动填入,提高用户体验. 首先我们看一下如何监听手机短信. 一.获取短信全部内容 1.新建一个SMSBroadcastReceiver: <code class="hljs java has-numbering"><span class="hljs-keyword">package</s

Android 监听短信2种方式:Broadcast和ContentObserver

1. 基于Broadcast接受短信 1.1 原理 Android收到短信后系统会发送一个android.provider.Telephony.SMS_RECEIVED广播.把它放在Bundle(intent.Extras)中,Bundle可以理解为一个Map,短信采用"pdus"作为键,pdus应该是protocol description units的简写,也就是一组短信.Android不是一接收到短信就立刻发出广播的,他会有一定的延迟,所以就有可能会有多条短信,所以才会用数组来存

(七)android开发中两种方式监听短信的原理和实现

一.监听短信的两种方式的简介 Android程序开发中,有两种方式监听短信内容:一.接收系统的短信广播:二.应用观察者模式,监听短信数据库. 第一种方式接收系统的短信广播: A.这种方式只对新收到的短消息有效,运行代码,并不会读取收件箱中已读或未读的消息,只有当收到新来的短消息时,才会执行onReceive()方法. B.并且这个广播是有序广播,如果当别的程序先读取到了这个广播,然后拦截掉了个这个广播,你将接收不到.当然我们可以通过设置priority的数值,其实有时是不管用的,现在在一些定制的

Android 监听短信 两种方式

1. 接受系统的短信广播,操作短信内容. 优点:操作方便,适合简单的短信应用. 缺点:来信会在状态栏显示通知信息. AndroidManifest.xml: <uses-permission android:name="android.permission.SEND_SMS"></uses-permission> <uses-permission android:name="android.permission.RECEIVE_SMS"

Android 监听短信(同时监听广播和数据库)

暗扣,强烈谴责这种侵害用户利益的行为... 下面给大家介绍Android暗扣原理.......  Android4.4以下的系统玩游戏就要小心了哈 暗扣方式之一:短信订购,即监听--------拦截------------处理短信. 暗扣方式之二:模拟人为操作(又叫模拟流量),通过后台程序代码模拟人的点击行为,暗自给用户订购业务,由运营商收取你的费用,当然这其中也需要涉及监听/拦截/处理短信.使用这种方式的原理无非是Http处理网页,还涉及接入点切换问题,这里就不详细讲解. 回归正题:有的时候,

Android实战简易教程-第三十六枪(监听短信-实现短信验证码自动填入)

一般用户喜欢用手机号作为用户名注册APP账号,这时一般都是通过手机验证码的方式进行验证,下面我们就研究一个非常实用的方法,通过监听短信-实现短信验证码的自动填入,提高用户体验. 首先我们看一下如何监听手机短信. 一.获取短信全部内容 1.新建一个SMSBroadcastReceiver: package com.example.messagecut; import java.text.SimpleDateFormat; import java.util.Date; import android.

android菜鸟学习笔记23----ContentProvider(三)利用内置ContentProvider监听短信及查看联系人

要使用一个ContentProvider,必须要知道的是它所能匹配的Uri及其数据存储的表的结构. 首先想办法找到访问短信及联系人数据的ContentProvider能接受的Uri: 到github上找对应ContentProvider的源码:https://github.com/android 有好多个,哪一个才是短信数据的ContentProvider呢? 在filters输入框:输入telephony. 现在只有一个了,打开: 装有git的话,可以选择clone到本地,没有的话,就选择下载

android 监听短信并发送到服务器

1. 接受系统的短信广播,操作短信内容. 优点:操作方便,适合简单的短信应用. 缺点:来信会在状态栏显示通知信息. 2. 应用观察者模式,监听短信数据库,操作短信内容.   实例如下: SystemEventReceiver:收到开机启动OK的广播后,启动BootService服务:收到应用发送短信的INTENT后,调用系统接口发送短信 BootService:开启服务后,打开短信监听器 SMSObserver:数据观察者,监听短信数据库 SMSHandler:短信处理器

通过broadcastreceiver 监听短信问题

在mainfest中 订阅   短信到来的广播时候  发现找不到 <action android:name="android.provider.Telephony.SMS_RECEIVED"> 目前未找到原因, 不知道,采用通过代码订阅广播方式 会不会成功 目前尚未验证 在网上人的回答 链接:https://www.zhihu.com/question/28521646/answer/64531805来源:知乎 1   因为这个广播很容易被不法分子拿来使用. google公