欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

安卓【AlarmManager】实现周期性定时执行某项任务(每15分钟监听手机接收到的短信数量)- 轮询

程序员文章站 2022-03-10 23:42:45
引言:AlarmManager,Timer都可以实现安卓中的定时任务。但是对于一些后台任务,往往需要在cpu处于非唤醒状态时执行。使用AlarmManager结合BroadCastReceiver以及Service就能实现轮询效果。分析:在我这个demo里面,我将实现一个 “每15分钟监听手机接收到的短信数量” 的程序。当这段时间内接收的短信数量>我们设置的阈值,将会提示当前接收的短信数量,并开始下一次监听。手机收到短信时,系统会发送一条广播,我们可以定义接收器捕捉这个广播。为了程序能够后台运行...

引言:
AlarmManager,Timer都可以实现安卓中的定时任务。但是对于一些后台任务,往往需要在cpu处于非唤醒状态时执行。使用AlarmManager结合BroadCastReceiver以及Service就能实现轮询效果。

分析:
在我这个demo里面,我将实现一个 “每15分钟监听手机接收到的短信数量” 的程序。当这段时间内接收的短信数量>我们设置的阈值,将会提示当前接收的短信数量,并开始下一次监听。手机收到短信时,系统会发送一条广播,我们可以定义接收器捕捉这个广播。为了程序能够后台运行,我们还需要一个服务用来每15分钟对短信数量做出反应。
整个程序的构建可以用一张图来概括:
安卓【AlarmManager】实现周期性定时执行某项任务(每15分钟监听手机接收到的短信数量)- 轮询
代码:
MainActivity.java

package com.example.smstest;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    IntentFilter filter;
    MySmsReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //RECEIVE_SMS属于危险权限,需要动态申请
        judegeRequest();
    }

    private void registerBroadCast() {
        filter=new IntentFilter();

        filter.addAction("android.provider.Telephony.SMS_RECEIVED" ); //手机收到短信时响应
        filter.addAction("android.intent.handle.num"); //我们自定义的 用于处理短信数量的广播

        receiver=new MySmsReceiver();
        registerReceiver(receiver,filter);//动态注册广播接收器,防止静态失效

        startService(new Intent(this,MyService.class)); //启动服务以进行计时
    }

    private void judegeRequest() {
        //6.0以上需要动态申请权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.RECEIVE_SMS) != PackageManager.PERMISSION_GRANTED) {
                requestPermissions(new String[]{Manifest.permission.RECEIVE_SMS},1);
            } else{
                registerBroadCast();
            }
        }else{
            registerBroadCast();
        }
    }


    @Override
    protected  void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);//解绑广播接收器
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case 1:
                if (grantResults.length > 0 &&
                        grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    registerBroadCast();
                }
                break;
        }
    }
}

MySmsReceiver.java

package com.example.smstest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;
public class MySmsReceiver extends BroadcastReceiver {

    private int count;

    public MySmsReceiver() {
        super();
        count=0;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getAction()==null) return;
        switch (intent.getAction()){
            case "android.intent.handle.num":
                handleNum(context);
                break;
            default:
                count++;
                break;
        }
    }

    private void handleNum(Context context) {
        //我们阈值为30条短信
        if(count>=30){
            Toast.makeText(context, "Detected excessive SMS activity: "+count+" messages", Toast.LENGTH_SHORT).show();
        }
        count=0;
        //重启服务以实现定时执行
        context.startService(new Intent(context,MyService.class));
    }
}

MyService.java

package com.example.smstest;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.os.SystemClock;
import android.widget.Toast;

public class MyService extends Service {

    private String action="android.intent.handle.num";
    private static int MINUTE = 15*60000; //十五分钟 即15*60*1000毫秒
    private AlarmManager manager; //用于实现定时功能

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        manager=(AlarmManager) getSystemService(ALARM_SERVICE);
        long triggerAtTime = SystemClock.elapsedRealtime() + MINUTE;
        Intent intent1=new Intent(action);
        PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent1, 0);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
        } else {
            manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
        }
        return super.onStartCommand(intent, flags, startId);
    }

}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.smstest">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".MySmsReceiver">
            <intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
                <action android:name="android.intent.handle.num"/>
            </intent-filter>
        </receiver>

        <service android:name=".MyService">

        </service>
    </application>

</manifest>

本文地址:https://blog.csdn.net/tran_sient/article/details/108143007