You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过BroadcastReceiver匹配指定短信并替换短信通知铃声

实现特定短信自定义通知音并静音系统默认通知

嘿,我来帮你搞定这个需求!要实现「收到包含指定词汇的短信时,替换为SD卡音频并静音系统默认通知」的功能,需要从拦截系统广播、播放自定义音频、权限配置这三个核心点入手,下面一步步拆解并补全代码:

一、先配置必要权限

首先在AndroidManifest.xml中添加所需权限,同时给你的BroadcastReceiver设置高优先级(确保能先于系统短信应用收到广播):

<!-- 短信相关权限 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<!-- 访问SD卡音频文件权限(Android 13+可替换为READ_MEDIA_AUDIO) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" android:minSdkVersion="33" />
<!-- 播放音频权限 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

<!-- 注册BroadcastReceiver,设置高优先级 -->
<receiver android:name=".SmsCustomReceiver" android:exported="true">
    <intent-filter android:priority="999">
        <action android:name="android.provider.Telephony.SMS_RECEIVED" />
    </intent-filter>
</receiver>

注意:Android 6.0及以上,RECEIVE_SMS、READ_EXTERNAL_STORAGE属于危险权限,需要在代码中动态申请,用户授权后才能生效。

二、补全BroadcastReceiver的核心逻辑

在你现有代码的基础上,添加拦截系统广播和播放自定义音频的逻辑:

public class SmsCustomReceiver extends BroadcastReceiver {
    private MediaPlayer mMediaPlayer;

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) {
            final Bundle bundle = intent.getExtras();
            try {
                if (bundle != null) {
                    final Object[] pdusObj = (Object[]) bundle.get("pdus");
                    for (int i = 0; i < pdusObj.length; i++) {
                        SmsMessage currentMessage = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
                        String address = currentMessage.getDisplayOriginatingAddress();
                        String smsBody = currentMessage.getDisplayMessageBody();

                        // 检查短信内容是否包含指定词汇
                        if (smsBody.contains("hello")) {
                            // 1. 拦截系统默认通知:终止广播传递,阻止系统短信应用处理
                            abortBroadcast();

                            // 2. 播放SD卡中的自定义音频
                            playCustomSound(context);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void playCustomSound(Context context) {
        // 替换为你SD卡中音频文件的路径,比如根目录下的custom_notify.mp3
        String soundPath = Environment.getExternalStorageDirectory().getPath() + "/custom_notify.mp3";
        File soundFile = new File(soundPath);

        if (!soundFile.exists()) {
            Toast.makeText(context, "自定义音频文件不存在", Toast.LENGTH_SHORT).show();
            return;
        }

        // 初始化MediaPlayer播放音频
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
        }
        mMediaPlayer = new MediaPlayer();
        try {
            mMediaPlayer.setDataSource(soundPath);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
            mMediaPlayer.prepare();
            mMediaPlayer.start();
            // 播放完毕后释放资源
            mMediaPlayer.setOnCompletionListener(mp -> {
                mp.release();
                mMediaPlayer = null;
            });
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(context, "播放音频失败", Toast.LENGTH_SHORT).show();
        }
    }
}

三、关键细节说明

  • 拦截系统广播:abortBroadcast()只能用于有序广播,而SMS_RECEIVED_ACTION正是有序广播,设置高优先级后我们的Receiver会先收到广播,调用这个方法就能阻止后续的Receiver(比如系统短信应用)处理,从而静音系统默认通知。
  • 自定义音频播放:使用MediaPlayer并指定STREAM_NOTIFICATION音频流,确保和系统通知音使用同一流,不会干扰其他音频播放;播放完毕后记得释放资源,避免内存泄漏。
  • Android版本兼容:
    • Android 10+访问外部存储时,直接用Environment.getExternalStorageDirectory()可能受限,建议使用MediaStore查询音频文件,或者将音频放在应用专属外部目录(context.getExternalFilesDir(Environment.DIRECTORY_MUSIC)),这样无需额外权限。
    • Android 13+需要申请READ_MEDIA_AUDIO权限替代READ_EXTERNAL_STORAGE。

四、动态申请权限示例

在你的MainActivity中添加动态权限申请逻辑:

private static final int REQUEST_PERMISSIONS = 1001;
private String[] permissions = {
        Manifest.permission.RECEIVE_SMS,
        Manifest.permission.READ_SMS,
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ?
                Manifest.permission.READ_MEDIA_AUDIO : Manifest.permission.READ_EXTERNAL_STORAGE
};

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (checkSelfPermission(permissions[0]) != PackageManager.PERMISSION_GRANTED ||
                checkSelfPermission(permissions[1]) != PackageManager.PERMISSION_GRANTED ||
                checkSelfPermission(permissions[2]) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(permissions, REQUEST_PERMISSIONS);
        }
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == REQUEST_PERMISSIONS) {
        boolean allGranted = true;
        for (int result : grantResults) {
            if (result != PackageManager.PERMISSION_GRANTED) {
                allGranted = false;
                break;
            }
        }
        if (!allGranted) {
            Toast.makeText(this, "请授予必要权限以使用功能", Toast.LENGTH_SHORT).show();
        }
    }
}

内容的提问来源于stack exchange,提问作者user5050715

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:46:41