android锁屏

(基于framework 目录下)
一、base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java 
     开机执行到:systemReady()方法,调用  mKeyguardMediator.onSystemReady();开始锁屏
     修改是否锁屏
          public void systemReady() {
          if (mKeyguardMediator != null) {
               try {
               //自己添加的,一个变量,如果是0,表示不锁屏,其他锁屏
                    int lock=Settings.System.getInt(mContext.getContentResolver(), "password_switch");
                    if(lock!=0){
                         mKeyguardMediator.onSystemReady();
                    }
               } catch (SettingNotFoundException e) {
               }
          }
          synchronized (mLock) {
               updateOrientationListenerLp();
               mSystemReady = true;
               mHandler.post(new Runnable() {
                    public void run() {
                         updateSettings();
                    }
               });
          }
     }
    
二、base/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
     执行:onSystemReady()方法,
     设置锁屏超时时间:
     修改 base\services\java\com\android\server\power\PowerManagerService.java
     文件中的  MINIMUM_SCREEN_OFF_TIMEOUT 常量,默认为 10*1000.
                             
     private boolean mExternallyEnabled = true;   此变量控制是否显示锁屏,true 锁,false 不锁

三、直接显示密码输入界面:
     base/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
     修改:void showPrimarySecurityScreen(boolean turningOff)方法体,
     showSecurityScreen(securityMode);==>showSecurityScreen(SecurityMode.SimPin);
    
四、解锁失败后,直接关机:
     base/services/java/com/android/server/power/PowerManagerService.java
     修改:private void updateDisplayPowerStateLocked 方法体:
     添加:shutdown(false,false);
     if (newScreenState != mDisplayPowerRequest.screenState) {
                if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF
                        && mDisplayPowerRequest.screenState
                                != DisplayPowerRequest.SCREEN_STATE_OFF) {
                    mLastScreenOffEventElapsedRealTime = SystemClock.elapsedRealtime();
                }

                mDisplayPowerRequest.screenState = newScreenState;
              //add by ytmfdw ,no screen off ,to shutdown
                shutdown(false, false);
//                nativeSetPowerState(
//                        newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF,
//                        newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
            }
    
五、锁屏密码验证
     如果显示的是: SecurityMode.SimPin
     base/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPinView.java
     修改:CheckSimPin类:
          run()方法里,修改验证代码
          verifyPasswordAndUnlock()方法里,修改密码长度验证
         
     如果显示的是: SecurityMode.SimPuk
     base/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSimPukView.java
          修改:CheckSimPuk类:
               run()方法里,修改验证代码
               private boolean checkPuk(),修改密码长度验证
               private boolean checkPin(),修改密码长度验证



应用程序调用锁屏分析:

private DevicePolicyManager dpm; 
 private void sysLock(){
       dpm = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE); 
       boolean active = dpm.isAdminActive(componentName);
       if (active) {
            dpm.lockNow();
       }
  } 


DevicePolicyManagerService.java        
(包名:package com.android.server;)

public void lockNow() {
        synchronized (this) {
            // This API can only be called by an active device admin,
            // so try to retrieve it to check that the caller is one.
            getActiveAdminForCallerLocked(null,
                    DeviceAdminInfo.USES_POLICY_FORCE_LOCK);
            lockNowUnchecked();
        }
    }


->lockNowUnChecked();

private void lockNowUnchecked() {
        long ident = Binder.clearCallingIdentity();
        try {
            // Power off the display
            getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
                    PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
            // Ensure the device is locked
            getWindowManager().lockNow(null);
        } catch (RemoteException e) {
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

->getWindowManager().lockNow(null);
调用的是WindowManagerService.java中的
(包名:package com.android.server.wm;)

 public void lockNow(Bundle options) {
        mPolicy.lockNow(options);
    }

mPolicy.lockNow(options)调用的是:
PhoneWindowManager.java中的
(包名:package com.android.internal.policy.impl;)
public void lockNow(Bundle options) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
        mHandler.removeCallbacks(mScreenLockTimeout);
        if (options != null) {
            // In case multiple calls are made to lockNow, we don't wipe out the options
            // until the runnable actually executes.
            mScreenLockTimeout.setLockOptions(options);
        }
        mHandler.post(mScreenLockTimeout);
    }

mHandler.post(mScreenLockTimeout); 执行的是:
(PhoneWindowManager.java中的内部类)
 class ScreenLockTimeout implements Runnable {
        Bundle options;
        @Override
        public void run() {
            synchronized (this) {
                if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
                if (mKeyguardMediator != null) {
                    mKeyguardMediator.doKeyguardTimeout(options);
                }
                mLockScreenTimerActive = false;
                options = null;
            }
        }
        public void setLockOptions(Bundle options) {
            this.options = options;
        }
    }

mKeyguardMediator.doKeyguardTimeout(options);调用的是
KeyguardViewMediator.java中的
(包名:package com.android.internal.policy.impl.keyguard;)
 public void doKeyguardTimeout(Bundle options) {
        mHandler.removeMessages(KEYGUARD_TIMEOUT);
        Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT, options);
        mHandler.sendMessage(msg);
    }

mHandler处理KEYGUARD_TIMEOUT消息:

 case KEYGUARD_TIMEOUT:
                    synchronized (KeyguardViewMediator.this) {
                        doKeyguardLocked((Bundle) msg.obj);
                    }
                    break;


doKeyguardLocked((Bundle) msg.obj); 调用的是:
KeyguardViewMediator.java中的
showLocked(options);

 private void showLocked(Bundle options) {
        if (DEBUG) Log.d(TAG, "showLocked");
        // ensure we stay awake until we are finished displaying the keyguard
        mShowKeyguardWakeLock.acquire();
        Message msg = mHandler.obtainMessage(SHOW, options);
        mHandler.sendMessage(msg);
    }

mHandler处理SHOW消息:
 case SHOW:
                    handleShow((Bundle) msg.obj);
                    return ;

  handleShow((Bundle) msg.obj); 调用的是:
KeyguardViewManager.java中的
(包名:package com.android.internal.policy.impl.keyguard;)
 mKeyguardViewManager.show(options);
这里面调用的是:
maybeCreateKeyguardLocked(enableScreenRotation, false, options);
接下来调用:
inflateKeyguardView(options);
### Android 机制实现与解决方案 #### 一、机制概述 Android机制主要通过 `KeyguardManager` 和 `PowerManager` 来管理设备的幕状态以及定行为。当设备进入状态时,CPU 可能会被置入低功耗模式,这会影响应用中的定时器、服务以及其他后台操作的行为。 为了应对这些情况,开发者可以采用多种方式来确保应用在状态下仍能正常运行。以下是几种常见的实现方法及其对应的解决方案: --- #### 二、保持 Service 运行并模拟音频播放 一种常见的方式是在时启动一个前台服务 (Foreground Service),并通过该服务播放一段无声的 MP3 文件以防止系统将应用判定为闲置而终止其进程[^1]。 ```java public class SilentAudioService extends Service { private MediaPlayer mediaPlayer; @Override public int onStartCommand(Intent intent, int flags, int startId) { mediaPlayer = new MediaPlayer(); try { AssetFileDescriptor afd = getAssets().openFd("silent.mp3"); mediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); mediaPlayer.prepare(); mediaPlayer.setLooping(true); mediaPlayer.start(); } catch (IOException e) { stopSelf(); } return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); if (mediaPlayer != null && mediaPlayer.isPlaying()) { mediaPlayer.stop(); mediaPlayer.release(); } } @Nullable @Override public IBinder onBind(Intent intent) { return null; } } ``` 上述代码展示了如何创建一个播放无声音频的服务,并将其设为循环播放。需要注意的是,这种方式可能会增加电量消耗,因此应谨慎使用。 --- #### 三、解决 Handler 和 CountDownTimer 停止运行的问题 当设备进入或休眠状态时,系统的 CPU 将被关闭,从而导致基于消息队列的任务(如 `Handler` 或 `CountDownTimer`)无法继续执行。可以通过以下两种方式进行改进[^2]: 1. **WakeLock** 使用 PowerManager 提供的 WakeLock API 获取部分唤醒权限,使 CPU 即使在幕熄灭的情况下也能维持运行。 ```java PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyApp::WakeLockTag"); wakeLock.acquire(); // 执行任务... wakeLock.release(); ``` 2. **AlarmManager 配合 Broadcast Receiver** 利用 AlarmManager 定期触发广播接收器,即使在情况下也可以重新激活计时逻辑。 ```java Intent alarmIntent = new Intent(context, MyBroadcastReceiver.class); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0); AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE); long triggerTime = System.currentTimeMillis() + intervalMillis; alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent); ``` 这两种方法各有优劣,需根据具体需求权衡选择。 --- #### 四、持续定位功能的支持 对于需要长时间进行 GPS 跟踪的应用程序来说,安卓高版本引入了更严格的省电策略,可能导致后位置更新中断。针对此问题可采取如下措施[^3]: 1. **请求前台服务权限** 创建一个带有通知栏提示的 Foreground Service 并绑定至 LocationClient 上。 ```java Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Location Tracking") .setSmallIcon(R.drawable.ic_location).build(); startForeground(NOTIFICATION_ID, notification); ``` 2. **配置 Battery Optimization 白名单** 引导用户手动将应用程序加入电池优化例外列表中,减少因 Doze Mode 导致的影响。 ```java Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + getPackageName())); startActivity(intent); ``` 以上手段能够有效缓解大部分场景下的定位丢失现象。 --- #### 五、禁用默认界面 如果目标是完全移除标准密码输入框,则可通过修改 AOSP Framework 参数达成目的[^4]。例如编辑 `config_enableKeyguardService` 设置项为 false 后编译生成自定义 ROM 版本即可生效。 ```xml <bool name="config_enableKeyguardService">false</bool> ``` 不过这种方法仅适用于拥有源码控制权的企业级环境部署场合,普通第三方 APP 不具备此类能力。 --- ### 总结 综上所述,面对 Android 系统带来的挑战可以从多个角度出发寻找对策,包括但不限于借助多媒体资源强制活跃进程、运用高级电源管理模式保障核心组件在线时间延长以及调整框架层参数规避干扰等等。每种技术都有各自适应范围,请依据实际业务诉求合理选用最佳实践组合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值