Android 屏保功能实现


需求-场景

Android机器实现息屏方式同时,实现屏保功能。如果是屏保,定时进入屏保。

需求场景来源

1)Android产品自带息屏时间,可以选择息屏时间,时间到后自动进入息屏状态。
2)切换一种模式,如果是屏保模式,那么时间到后进入屏保。
3)更多的需求是自定义屏保功能,实现客制化需求。 暂不考虑 相关资料可参考

延伸知识点

很多上电不带电池工控产品,不用考虑电池电量问题。息屏模式下屏幕黑的给人感觉不太好。
息屏情况下,亮屏逻辑有两种,点触亮屏和按键亮屏。【点触也是将屏幕触摸功能打开,亮度熄灭逻辑】。
如果机器产品没有触摸亮屏功能,亮屏幕必须按键亮屏,比较麻烦。
实现屏保功能,息屏时间到时候直接进入屏保,提升交互体验。

息屏关闭屏幕亮度+进入屏保界不关闭屏幕亮度+是否点触亮屏 各有优劣,不同需求和用户习惯场景都有自身存在的价值。


参考资料

Android 10 如何自定义屏保功能:
Android 屏保开关:
Android 系统默认屏保:
Android R DreamManagerService分析:
息屏显示实现
Android - PowerManagerService 启动:
publishBinderService和publishLocalService区别:
Android系統中的LocalService:

相关资源需要看一看,了解基本的知识内容,同时在解决问题的过程中针对性的再次看看相关资料参考,会有很大的帮助的。

界面引导

比如我们需要实现的界面如下,屏保模式、屏保时间、屏幕模式

在这里插入图片描述

屏保功能在 设置->显示->屏保 可以选择屏保,界面如下

在这里插入图片描述

如果选择了屏保则立即进入选择的屏保

在这里插入图片描述

源码分析

StartNowPreferenceController

从设置界面,立即启动屏保界面查看源码

fise4@ubuntu-PowerEdge-R730:~/Android/mt6769-alps-release-s0.mp1.rc/alps-release-s0.mp1.rc$ find . -name StartNowPreferenceController.java
./packages/apps/Settings/src/com/android/settings/dream/StartNowPreferenceController.java
./vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/dream/StartNowPreferenceController.java


/**
 * Controller that used to enable screen saver
 */
public class StartNowPreferenceController extends SettingsMainSwitchPreferenceController {
   

    private final DreamBackend mBackend;
    private final MetricsFeatureProvider mMetricsFeatureProvider;

    public StartNowPreferenceController(Context context, String preferenceKey) {
   
        super(context, preferenceKey);
        mBackend = DreamBackend.getInstance(context);
        mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
    }

    @Override
    public int getAvailabilityStatus() {
   
        return AVAILABLE;
    }

    @Override
    public void updateState(Preference preference) {
   
        mSwitchPreference.setChecked(false);
        mSwitchPreference.setEnabled(mBackend.getWhenToDreamSetting() != DreamBackend.NEVER);
    }

    @Override
    public boolean isChecked() {
   
        return false;
    }

    @Override
    public boolean setChecked(boolean isChecked) {
   
        if (isChecked) {
   
            if (mSwitchPreference != null) {
   
                mMetricsFeatureProvider.logClickedPreference(mSwitchPreference,
                        mSwitchPreference.getExtras().getInt(DashboardFragment.CATEGORY));
            }
            mBackend.startDreaming();
        }
        return true;
    }
}

核心代码:

    @Override
    public boolean setChecked(boolean isChecked) {
   
        if (isChecked) {
   
            if (mSwitchPreference != null) {
   
                mMetricsFeatureProvider.logClickedPreference(mSwitchPreference,
                        mSwitchPreference.getExtras().getInt(DashboardFragment.CATEGORY));
            }
            mBackend.startDreaming();
        }
        return true;
    }

DreamDreamBackend.java

/frameworks/base/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
	

    public void startDreaming() {
   
        logd("startDreaming()");
        if (mDreamManager == null)
            return;
        try {
   
            mDreamManager.dream();
        } catch (RemoteException e) {
   
            Log.w(TAG, "Failed to dream", e);
        }
    }

所以,立即进入屏保最终调用方法 mDreamManager.dream()方法


 mDreamManager  定义:
private final IDreamManager mDreamManager;


 //获取DreamManager的实例‌:使用getSystemService()方法并 来获取DreamManager的实例。	
 mDreamManager = IDreamManager.Stub.asInterface(
                ServiceManager.getService(DreamService.DREAM_SERVICE));

DreamManagerService.java


==>\frameworks\base\core\java\android\service\dreams\IDreamManager.aidl
==>/frameworks/base/services/core/java/com/android/server/dreams/DreamManagerService.java	

  @Override // Binder call
        public void dream() {
   
            checkPermission(android.Manifest.permission.WRITE_DREAM_STATE);

            final long ident = Binder.clearCallingIdentity();
            try {
   
                requestDreamInternal();
            } finally {
   
                Binder.restoreCallingIdentity(ident);
            }
        }



    private void requestDreamInternal() {
   
        // Ask the power manager to nap.  It will eventually call back into
        // startDream() if/when it is appropriate to start dreaming.
        // Because napping could cause the screen to turn off immediately if the dream
        // cannot be started, we keep one eye open and gently poke user activity.
        long time = SystemClock.uptimeMillis();
        mPowerManager.userActivity(time, true /*noChangeLights*/);
        mPowerManager.nap(time);
    }
	

屏保的立即开启 居然进入到了PowerManagerService 里面

mPowerManager 定义和初始化地方:
PowerManager mPowerManager;  
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);

PowerManagerService

nap 方法跟踪

./frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java

nap ->dreamDisplayGroup ->updatePowerStateLocked->

@Override // Binder call
        public void nap(long eventTime) {
   
            if (eventTime > mClock.uptimeMillis()) {
   
                throw new IllegalArgumentException("event time must not be in the future");
            }

            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);

            final int uid = Binder.getCallingUid();
            final long ident = Binder.clearCallingIdentity();
            try {
   
                dreamDisplayGroup(Display.DEFAULT_DISPLAY_GROUP, eventTime, uid);
            } finally {
   
                Binder.restoreCallingIdentity(ident);
            }
        }


   private void dreamDisplayGroup(int groupId, long eventTime, int uid) {
   
        synchronized (mLock) {
   
            if (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野火少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值