跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Android 锁屏服务实现与电话状态监听

Android 锁屏服务通过注册屏幕开关广播和电话状态监听器实现。服务启动后禁用锁屏,监听通话状态变化(空闲、振铃、挂断)。当屏幕关闭且处于空闲状态时,延迟触发锁屏界面跳转,并维持 CPU 运行以确保任务执行。代码展示了 KeyguardManager 和 TelephonyManager 的具体用法。

DevStack发布于 2025/1/17更新于 2026/9/555 浏览
Android 锁屏服务实现与电话状态监听

Android 锁屏服务实现

功能概述

该服务类主要处理屏幕开关广播及电话状态监听。启动后首先注册接受屏幕的关闭和开启的广播,在广播中处理开屏锁屏任务;获取电话管理服务,注册通话状态监听,监听手机响铃状态、挂起状态、空闲状态,以 Handler 方式执行不同的任务。

核心逻辑

  1. 屏幕监听:注册 ACTION_SCREEN_OFF 和 ACTION_SCREEN_ON 广播。
  2. 电话监听:使用 PhoneStateListener 监听通话状态变化。
  3. 锁屏控制:通过 KeyguardManager 禁用或启用锁屏。
  4. 任务调度:利用 Handler 处理延迟锁屏跳转及唤醒锁管理。
import android.app.KeyguardManager;
import android.app.Service;
import android.app.KeyguardManager.KeyguardLock;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;

public class LockService extends Service {
    protected static final String TAG = "SAFLockService";
    KeyguardManager mKeyguardManager;
    private KeyguardLock mKeyguardLock = null;
    private TelephonyManager tm;
    private Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this.getApplicationContext();

        Log.v(TAG, "=============onCreate:================");
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(Intent.ACTION_SCREEN_ON);
        registerReceiver(mScreenReceiver, filter);

        mKeyguardManager = (KeyguardManager) this.getSystemService(Context.KEYGUARD_SERVICE);
        mKeyguardLock = mKeyguardManager.newKeyguardLock("");
        mKeyguardLock.disableKeyguard();

        tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
        SAFLockPhoneCallListener myPhoneCallListener = new SAFLockPhoneCallListener();
        tm.listen(myPhoneCallListener, PhoneStateListener.LISTEN_CALL_STATE);

        SAFLockConstants.loadInitParam(this);
        this.setForeground(true);
    }

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

    @Override
    public void onDestroy() {
        super.onDestroy();
        mKeyguardLock.reenableKeyguard();
        mHandler.removeMessages(SAFLockConstants.EVENT_LOCK_SCREEN);
        unregisterReceiver(mScreenReceiver);
    }

    /**
     * set a listener to listen the phonestate,that we can do somthing by one
     * of phonestates.
     *
     * @author liao
     */
    public class SAFLockPhoneCallListener extends PhoneStateListener {
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
                // Phone in idle
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.v(TAG, "=============CALL_STATE_IDLE:================");
                    SAFLockConstants.PHONE_STATE = TelephonyManager.CALL_STATE_IDLE;
                    if (SAFLockConstants.isLockecd) {
                        mHandler.removeMessages(SAFLockConstants.EVENT_LOCK_SCREEN);
                        mHandler.sendEmptyMessage(SAFLockConstants.EVENT_LOCK_SCREEN);
                    }
                    break;
                // Phone is hung up
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.v(TAG, "=============CALL_STATE_OFFHOOK:================");
                    SAFLockConstants.PHONE_STATE = TelephonyManager.CALL_STATE_OFFHOOK;
                    break;
                // Cell phone ring
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.v(TAG, "=============CALL_STATE_RINGING:================");
                    SAFLockConstants.PHONE_STATE = TelephonyManager.CALL_STATE_RINGING;
                    break;
                default:
                    Log.v(TAG, "=============default:================");
                    break;
            }
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SAFLockConstants.EVENT_LOCK_SCREEN:
                    // ====read user customization
                    SAFLockConstants.updateLockIntent(
                            "saf.cmcc.lock.THEME_DEFAULT", mContext);

                    // keep the task running 2s in sleeping mode.
                    PowerManager pm = (PowerManager) mContext
                            .getSystemService(Context.POWER_SERVICE);
                    // Keep the CPU running, and the screen and keyboard light may
                    // be closed.
                    PowerManager.WakeLock mWakeLock = pm.newWakeLock(
                            PowerManager.PARTIAL_WAKE_LOCK, "SAFLock");
                    mWakeLock.acquire(2000L);

                    Intent mLockScreenIntent = new Intent(mContext,
                            SAFFullScreenActivity.class);
                    mLockScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    mLockScreenIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
                    mContext.startActivity(mLockScreenIntent);
                    break;
                default:
                    break;
            }
        }
    };

    private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (Intent.ACTION_SCREEN_OFF.equalsIgnoreCase(action)) {
                // load intent
                if (SAFLockConstants.LOCK_ENABLE
                        && SAFLockConstants.PHONE_STATE == TelephonyManager.CALL_STATE_IDLE) {

                    // =====send message after a short delay
                    if (!SAFLockConstants.isLockecd) {
                        mHandler.removeMessages(SAFLockConstants.EVENT_LOCK_SCREEN);
                        mHandler.sendEmptyMessageDelayed(
                                SAFLockConstants.EVENT_LOCK_SCREEN, 100);
                    }
                }
            } else if (Intent.ACTION_SCREEN_ON.equalsIgnoreCase(action)) {
                // ====remove unprocessed event.
                mHandler.removeMessages(SAFLockConstants.EVENT_LOCK_SCREEN);
            }
        }
    };
}

目录

  1. Android 锁屏服务实现
  2. 功能概述
  3. 核心逻辑

更多推荐文章

查看全部
  • Python 与 Java:哪个更好,如何选择?
  • 安卓本地跑 Stable Diffusion 的开源工具
  • RCTF 2025 Web 部分解题思路与漏洞分析
  • AI 日报:万象有声公测、xAI 团队变动及微软 VibeVoice 开源
  • 用 Python requests 和 pytest 搭一个接口自动化框架
  • Gazebo 仿真环境搭建指南:构建逼真机器人测试场景
  • Java 设计模式:单例、工厂与代理模式
  • Linux UDP 网络编程
  • Web 安全漏洞挖掘实战:从信息收集到逻辑漏洞利用
  • Java Swing 网格布局 GridLayout 基础用法
  • 使用 OpenClaw 与飞书搭建专属 AI 机器人教程
  • 小米温湿度计固件改造与智能家居集成方案
  • C++ 矩阵翻转与 n*n 矩阵旋转实现
  • CNCjs Web 数控控制器配置指南:从安装到多场景应用
  • EasyConnect Mac 版安装使用指南
  • AI 产品经理挑战、程序员副业指南与大模型训练法则
  • C++类型约束实战精要
  • 基于 Java 与高德地图 API 的县域烟花销售点自动化盘点方案
  • agent-browser:Vercel 开源的 AI 智能体浏览器自动化 CLI 工具
  • 网络安全入门学习路径与核心课程资源指南

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online