口袋模式的实现

口袋模式的实现口袋模式 带有黑屏手势功能的手机 一般都需要进行一个防误触的判断

大家好,欢迎来到IT知识分享网。

口袋模式

口袋模式:带有黑屏手势功能的手机,一般都需要进行一个防误触的判断。防止手机放在口袋里或者包包(一些导电介质的东西可能带来辅助效果,比如钥匙)里别误触发点亮屏幕,甚至是打出电话。

口袋模式设计原理:接近式传感器的靠近与远离功能。可以参考我们手机打电话时,耳朵贴近手机的时候,往往屏幕是自动息屏,离开耳朵一小段距离,屏幕又亮起的这个功能。同理和我们放在口袋中一个意思。

概要设计

  1. 添加设置的各级菜单
  2. 获取距离传感器以及功能实现

功能实现

添加各级菜单

各级菜单的定义以及其界面的实现,主要是对交互界面的实现,除数据库的存储外,不涉及到逻辑的处理。

一、添加设置的各级菜单

添加模块:MtkSettings

添加菜单

路径: res/xml/gestures.xml

        <com.android.settingslib.PrimarySwitchPreference ​            android:key="pocket_mode" ​            android:title="@string/pocket_mode" ​            android:summary="@string/pocket_mode_tip" ​            settings:controller="com.android.settings.gestures.PocketModePreferenceController" />

添加字符串资源

路径:res/values/strings.xml

<string name="pocket_mode">Pocket Mode</string> ​ <string name="pocket_mode_tip">It can help users avoid accidental touch of the screen in their pockets or bags</string> ​

添加PocketModePreferenceController.java类

路径:这个类需要在gestures目录上自行添加。src/com/android/settings/gestures/PocketModePreferenceController.java

package com.android.settings.gestures; import static android.provider.Settings.Secure.TURN_ON_BACKLIGHT_GESTURE; import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.os.Handler; import android.os.SystemProperties; import android.provider.Settings; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; import com.android.settingslib.PrimarySwitchPreference; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; import com.google.common.annotations.VisibleForTesting; import java.io.DataOutputStream; import java.io.IOException; import android.database.ContentObserver; ​ public class PocketModePreferenceController extends TogglePreferenceController        implements LifecycleObserver, OnStart, OnStop { ​    @VisibleForTesting    static final int KEY_CHORD_POWER_VOLUME_UP_MUTE_TOGGLE = 1; ​    private Preference mPreference;    private SettingObserver mSettingObserver; ​    public PocketModePreferenceController(Context context, String preferenceKey) {        super(context, preferenceKey);   } ​    @Override    public void displayPreference(PreferenceScreen screen) {        super.displayPreference(screen);        mPreference = screen.findPreference(getPreferenceKey());        mSettingObserver = new SettingObserver(mPreference);   } ​    @Override    public boolean isChecked() {        final int status = Settings.Secure.getInt(mContext.getContentResolver(),                Settings.Secure.POCKET_MODE,0);        return status != 0;   } ​    @Override    public boolean setChecked(boolean isChecked) {        return Settings.Secure.putInt(mContext.getContentResolver(),                Settings.Secure.POCKET_MODE, isChecked ? 1 : 0);   } ​    @Override    public void updateState(Preference preference) {        super.updateState(preference);        CharSequence summary = mContext.getText(R.string.pocket_mode_tip);        preference.setSummary(summary);   } ​    @Override    public int getAvailabilityStatus() {        return SystemProperties.getBoolean("ro.config.wake_gesture", false) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;   } ​    @Override    public void onStart() {        if (mSettingObserver != null) {            mSettingObserver.register(mContext.getContentResolver());            mSettingObserver.onChange(false, null);       }   } ​    @Override    public void onStop() {        if (mSettingObserver != null) {            mSettingObserver.unregister(mContext.getContentResolver());       }   } ​ ​    private class SettingObserver extends ContentObserver {        private final Uri mGestureUri = Settings.Secure.getUriFor(                Settings.Secure.POCKET_MODE); ​        private final Preference mPreference; ​        SettingObserver(Preference preference) {            super(new Handler());            mPreference = preference;       } ​        public void register(ContentResolver cr) {            cr.registerContentObserver(mGestureUri, false, this);       } ​        public void unregister(ContentResolver cr) {            cr.unregisterContentObserver(this);       } ​        @Override        public void onChange(boolean selfChange, Uri uri) {            super.onChange(selfChange, uri);            if (uri == null || mGestureUri.equals(uri)) {                updateState(mPreference);           }       }   } ​    @Override    public int getSliceHighlightMenuRes() {        return 0;   } }

在getAvailabilityStatus()这个方法中,使用了宏控,可以根据实际需求自行选择开关的状态。各级菜单的定义以及其界面的实现,主要是对交互界面的实现,除数据库的存储外,不涉及到逻辑的处理。

二、获取距离传感器以及功能实现

添加模块:framework/base

目前智能亮屏方式有两种,抬腕亮屏和双击亮屏。口袋模式的实现方式则是针对这两种亮屏方式进行实现。当口袋模式打开的时候,pSensor如果检测到有物体靠近,就使抬腕亮屏和双击亮屏功能失效,否则,抬腕亮屏和双击亮屏功能正常实现。

设置数据库属性

路径: core/java/android/provider/Settings.java

        /         * @hide         */        public static final String POCKET_MODE =                "pocket_mode"; ​

获取距离的传感器ProximityCheck.java

路径:services/core/java/com/android/server/policy/ProximityCheck.java

package com.android.server.policy; ​ import android.view.KeyEvent; import android.os.Handler; import android.util.Slog; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.os.PowerManager; import android.os.PowerManager.WakeReason; import android.os.SystemClock; ​ public class ProximityCheck { ​    private final SensorManager mSensorManager;    private KeyEvent event;    private boolean mRegistered;    private final Handler mHandler;    static final String TAG = "ProximityCheck";    PowerManager mPowerManager; ​    ProximityCheck(Context context, Handler handler) {        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);        mPowerManager= (PowerManager) context.getSystemService(Context.POWER_SERVICE);        mHandler = handler;   } ​    private final SensorEventListener mSensorEventListener = new SensorEventListener() {        @Override        public void onSensorChanged(SensorEvent event) {            if (event.values.length == 0) {                Slog.w(TAG, "ProximityCheck Event has no values!");                finishWithResult(false);           } else {                boolean isNear = event.values[0] != 1.0f;                Slog.d(TAG, "ProximityCheck isNear:" + isNear+" "+event.values[0]);                finishWithResult(isNear);           }       } ​        @Override        public void onAccuracyChanged(Sensor sensor, int accuracy) { ​       }   }; ​    private final Runnable mTimeoutRunnable = () -> {        Slog.w(TAG, "ProximityCheck timeout!");        finishWithResult(false);   }; ​    public void onResult(boolean isNear) {        Slog.w(TAG, "ProximityCheck onResult:"+isNear);        if(isNear){            mPowerManager.goToSleep(SystemClock.uptimeMillis());       }   } ​    public void check() {        Slog.d(TAG, "ProximityCheck check");        mRegistered = true;        mSensorManager.registerListener(mSensorEventListener,                mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY), SensorManager.SENSOR_DELAY_NORMAL, mHandler);        mHandler.postDelayed(mTimeoutRunnable, 500);   } ​    private void finishWithResult(boolean isNear) {        onResult(isNear);        if (mRegistered) {            mRegistered = false;            mHandler.removeCallbacks(mTimeoutRunnable);            mSensorManager.unregisterListener(mSensorEventListener);       }   } }

口袋模式功能的实现PhoneWindowManager.java

路径:services/core/java/com/android/server/policy/PhoneWindowManager.java

1、声明ProximityCheck。

private ProximityCheck proximityCheck;

2、抬腕唤醒时,检测是否有物体靠近

在抬腕亮屏的onWakeUp方法中创建ProximityCheck对象,并获取到口袋模式的开关是否打开,如果打开则是调用ProximityCheck对象中的check方法。

{                if(proximityCheck == null ){                    proximityCheck = new ProximityCheck(mContext, mHandler);               }                if (shouldEnableWakeGestureLp()) {                    performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,                            "Wake Up");                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,                            PowerManager.WAKE_REASON_GESTURE, "android.policy:GESTURE");                    boolean pocketMode = Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.POCKET_MODE,0) != 0;                    if(pocketMode) {                        proximityCheck.check();                   }           }       } ​

3、双击唤醒时,检测是否有物体靠近

在interceptKeyBeforeQueueing方法中上报各种keycode的下面添加一个双击亮屏的case KeyEvent.keycode,然后创建ProximityCheck对象,并获取到口袋模式的开关是否打开,如果打开则是调用ProximityCheck对象中的check方法。

case KeyEvent.KEYCODE_U:                if(proximityCheck == null ){                    proximityCheck = new ProximityCheck(mContext, mHandler);               }                if(down){                    boolean pocketMode = Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.POCKET_MODE,0) != 0;                    mPowerManager.wakeUp(event.getEventTime(), PowerManager.WAKE_REASON_WAKE_KEY, "android:policy:double_click");                    if(pocketMode){                        proximityCheck.check();                   }               }                break; 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/121855.html

(0)
上一篇 2025-10-21 09:33
下一篇 2025-10-21 10:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信