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

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

分析:
在我这个demo里面,我将实现一个 “每15分钟监听手机接收到的短信数量” 的程序。当这段时间内接收的短信数量>我们设置的阈值,将会提示当前接收的短信数量,并开始下一次监听。手机收到短信时,系统会发送一条广播,我们可以定义接收器捕捉这个广播。为了程序能够后台运行,我们还需要一个服务用来每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>

猜你喜欢

转载自blog.csdn.net/tran_sient/article/details/108143007