Android原生代码定时读取手机短信内容

797 阅读2分钟

新版本Android由于数据安全限制,在读取短信内容前必须预先取得授权,不能直接在MainActivity中直接读取

若要定时读取Android内容,尽量使用服务(service)通知的形式,而不是直接使用Java Timer定时器,否则程序运行10s后自动退出

Android读取手机短信

1. AndroidManifest.xml 权限配置

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

2. 授权申请

if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) != PackageManager.PERMISSION_GRANTED
        && ActivityCompat.checkSelfPermission(context, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
    LOG.i("demo", "未申请到读取短信权限,请手动授权");
    return;
}
// 有了权限,即可读取短信内容

3. 读取短信内容

Uri uri = Uri.parse("content://sms/");
String[] projection = new String[] {"address", "body", "date"};
// 获取手机内部短信
Cursor cur = contentResolver.query(uri, projection, null, null, "date desc");
if (null != cur && cur.moveToFirst()) {
    int index_Address = cur.getColumnIndex("address");
    int index_Body = cur.getColumnIndex("body");
    int index_Date = cur.getColumnIndex("date");
    while(cur.moveToNext()) {
        String sender = cur.getString(cur.getColumnIndex("address"));
        String content = cur.getString(cur.getColumnIndex("body"));
        long timeMs = cur.getLong(cur.getColumnIndex("date"));
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
        Date d = new Date(timeMs);
        String createTime = dateFormat.format(d);
    };

    if (!cur.isClosed()) {
        cur.close();
        cur = null;
    }
}

Android定时器实现

1. 编写服务类,执行任务,并发消息给接收者,重新唤醒服务

public class AlarmService extends Service {

    //每10s更新一次数据
    private static final int ONE_Miniute = 10 * 1000;
    private static final int PENDING_REQUEST = 0;
    
    @Override
    public void onCreate() {
        super.onCreate();
        // 每次service创建,都发送消息给接收者,唤醒服务
        if (Build.VERSION.SDK_INT >= 26) {
            String CHANNEL_ID = "my_channel_01";
            NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                    "Channel human readable title",
                    NotificationManager.IMPORTANCE_DEFAULT);

            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle("")
                    .setContentText("").build();

            startForeground(1, notification);
        }
        Log.v("demo", "alarmService created");
    }

    /**
     * 调用Service都会执行到该方法
     */
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        String phone = SmsUtil.getPhone(getApplicationContext());
        if(null == phone) {
            return super.onStartCommand(intent, flags, startId);
        }

        // 定时执行任务
        new Thread(new Runnable() {
            @Override
            public void run() {
                Log.e("demo", "I am running");
            }
        }).start();

        //通过AlarmManager定时启动广播
        AlarmManager alarmManager= (AlarmManager) getSystemService(ALARM_SERVICE);
        //从开机到现在的毫秒书(手机睡眠(sleep)的时间也包括在内
        long triggerAtTime = SystemClock.elapsedRealtime()+ONE_Miniute;
        Intent i = new Intent(this, AlarmReceive.class);
        PendingIntent pIntent = PendingIntent.getBroadcast(this, PENDING_REQUEST,i, PendingIntent.FLAG_IMMUTABLE);
        alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,triggerAtTime,pIntent);

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

2. 编写接收类,唤醒服务

public class AlarmReceive extends BroadcastReceiver {

    public AlarmReceive() {
        super();
        Log.i("demo", "AlarmReceiver create");
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        //循环启动Service
        Intent i = new Intent(context, AlarmService.class);
        // 后台程序需使用startForegroundService启动服务
        context.startForegroundService(i);
    }
}

3. AndroidManifest.xml 配置service 和 receiver

<!-- 该权限也需要 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<service android:name=".AlarmService"/>
<receiver android:name=".AlarmReceive"/>