一.口袋模式定义
实际上很难判断手机是否处于口袋中,口袋场景太复杂,目前市场上口袋模式没有一个确定的定义,参考其它手机和自己做过产品。
定义:手机是处于竖立状态并且距离传感器是被遮挡。
实现原理:加速度传感器判断手机是否处于竖立状态,距离传感器判断是否被遮挡。
应用场景:1.来电铃声自动调到最大音,拿出口袋恢复之前声音大小。2.口袋模式下自动锁屏或灭屏,拿出口袋自动解锁或亮屏。。。可以根据产品定义功能。
下面代码是来电铃声自动调到最大音功能为例,该功能实在原生incallUi应用上实现,代码实现位置如下。
packages\apps\InCallUI\src\com\android\incallui\ProximitySensor.java
//变量声明 begin
private
static
final
float
CRITICAL_DOWN_ANGLE
=
-
8.0f
;
private
static
final
float
CRITICAL_UP_ANGLE
=
8.0f
;
private
static
final
int
SPEED_SHRESHOLD
=
800
;
private
SensorManager
mSensorManager
;
private
Sensor
mGsensorAccelerometer
;//加速度传感器
private Sensor mGsensorProximity;//距离传感器
private
int
mReverseDownFlg
=
-
1
;
private
float
lastX
;
private
float
lastY
;
private
float
lastZ
;
private
static
final
int
UPTATE_INTERVAL_TIME
=
70
;
private static final String POCKET_MODE = "pocket_mode_for_call";
float
tMax
=
1.0f
;
float
tMaxleft
=
0.1f
;
private
long
lastUpdateTime
;
SensorEventListener
mySensorListener
;
boolean
disInRang
=
false
;
int
previousMuteMode
=
-
1
;
boolean
mActFlag
=
false
;
boolean isPocket = false;
float distance = 10; float MAXRANGDISTANCE =1.0f;
int
previousRing
=
0
;
boolean
isRing
=
false
;
AudioManager
am
;
//变量声明 end
public
ProximitySensor
(
Context
context
,
AudioModeProvider
audioModeProvider
,
AccelerometerListener
accelerometerListener
)
{
mContext
=
context
;
mPowerManager
=
(
PowerManager
)
context
.
getSystemService
(
Context
.
POWER_SERVICE
);
if
(
mPowerManager
.
isWakeLockLevelSupported
(
PowerManager
.
PROXIMITY_SCREEN_OFF_WAKE_LOCK
))
{
mProximityWakeLock
=
mPowerManager
.
newWakeLock
(
PowerManager
.
PROXIMITY_SCREEN_OFF_WAKE_LOCK
,
TAG
);
}
else
{
Log
.
w
(
TAG
,
"Device does not support proximity wake lock."
);
mProximityWakeLock
=
null
;
}
mAccelerometerListener
=
accelerometerListener
;
mAccelerometerListener
.
setListener
(
this
);
mDisplayListener
=
new
ProximityDisplayListener
(
(
DisplayManager
)
context
.
getSystemService
(
Context
.
DISPLAY_SERVICE
));
mDisplayListener
.
register
();
mAudioModeProvider
=
audioModeProvider
;
mAudioModeProvider
.
addListener
(
this
);
//变量初始化 begin
am
=
(
AudioManager
)
mContext
.
getSystemService
(
Context
.
AUDIO_SERVICE
);
mSensorManager
=
(
SensorManager
)
mContext
.
getSystemService
(
Service
.
SENSOR_SERVICE
);
mGsensorAccelerometer
=
mSensorManager
.
getDefaultSensor
(
Sensor
.
TYPE_ACCELEROMETER
);
//获取加速度传感器
mSensorManager
.
registerListener
(
mGsensorListener
,
mGsensorAccelerometer
,
SensorManager
.
SENSOR_DELAY_NORMAL
);
//注册传感器监听
mGsensorProximity = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);/获取距离传感器 mSensorManager.registerListener(mGsensorListener, mGsensorProximity, SensorManager.SENSOR_DELAY_NORMAL);//注册传感器监听
//变量初始化 end
}
//传感器监听
SensorEventListener
mGsensorListener
=
new
SensorEventListener
()
{
@Override
public
void
onAccuracyChanged
(
Sensor
sensor
,
int
accuracy
)
{
}
@Override
public
void
onSensorChanged
(
SensorEvent
event
)
{
TelecomManager
telecomManager
=
getTelecommService
();
//获取telecom对象
if
(
telecomManager
!=
null
&&
telecomManager
.
isRinging
())
{
//判断当前是否响铃
sRing
=
true
;
}
else
{
//电话状态不再是响铃状态
isRing
=
false
;
Log
.
d
(
TAG
,
"telecomManager not ring "
);
//响铃停止恢复之前铃声大小
if(mActFlag){
mActFlag = false; am.setRingerMode(previousMuteMode); am.setStreamVolume(AudioManager.STREAM_RING,previousRing, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);
}
return
;
}
if(event.sensor.getType() == Sensor.TYPE_PROXIMITY){//如果是距离传感器
distance = event.values[0]; //获取值
Log.d(
TAG, "distance "+distance);
return; }
long
currentUpdateTime
=
System
.
currentTimeMillis
();
long
timeInterval
=
currentUpdateTime
-
lastUpdateTime
;
lastUpdateTime
=
currentUpdateTime
;
float
x
=
event
.
values
[
SensorManager
.
DATA_X
];
float
y
=
event
.
values
[
SensorManager
.
DATA_Y
];
float
z
=
event
.
values
[
SensorManager
.
DATA_Z
];
float
deltaX
=
x
-
lastX
;
float
deltaY
=
y
-
lastY
;
float
deltaZ
=
z
-
lastZ
;
float
absx
=
Math
.
abs
(
x
);
float
absy
=
Math
.
abs
(
y
);
float
absz
=
Math
.
abs
(
z
);
lastX
=
x
;
lastY
=
y
;
lastZ
=
z
;
double
speed
=
Math
.
sqrt
(
deltaX
*
deltaX
+
deltaY
*
deltaY
+
deltaZ
*
deltaZ
)/
timeInterval
*
10000
;
if
(
event
.
values
[
SensorManager
.
DATA_Z
]
>=
CRITICAL_UP_ANGLE
){
//屏幕竖直朝上
mReverseDownFlg
=
0
;
}
else
if
(
event
.
values
[
SensorManager
.
DATA_Z
]
<=
CRITICAL_DOWN_ANGLE
&&
mReverseDownFlg
==
0
){
//屏幕竖直朝下
mReverseDownFlg
=
1
;
}
if
(
absx
>
absy
&&
absx
>
absz
)
{
if
(
x
>
tMax
)
{
isPocket = false;
Log
.
d
(
TAG
,
"turn left"
+
" isLeftRight = "
+
isLeftRight
);
//手机向左边翻转
}
else
if
(
x
<
-
tMax
){
isPocket = false;
Log
.
d
(
TAG
,
"turn right"
+
" isLeftRight = "
+
isLeftRight
);
//手机向右边翻转
}
}
else
if
(
absy
>
absx
&&
absy
>
absz
)
{
if
(
y
>
tMax
)
{
isPocket = true;
Log
.
d
(
TAG
,
"turn up"
+
" isLeftRight = "
+
isLeftRight
);
//手机竖直翻转头向上
}
else
if
(
y
<-
tMax
){
isPocket = true;
Log
.
d
(
TAG
,
"turn down"
+
" isLeftRight = "
+
isLeftRight
);
//手机竖直翻转头向下
}
}
else
if
(
absz
>
absx
&&
absz
>
absy
)
{
if
(
z
>
0
)
{
isPocket = false;
Log
.
d
(
TAG
,
"screen up"
);
//手机屏幕向上
}
else
{
isPocket = false;
Log.d(TAG, "onSensorChanged set slince");//手机屏幕向下
}
Log
.
d
(
TAG
,
"screen down"
+
" isLeftRight = "
+
isLeftRight
);
}
}
else
{
Log
.
d
(
TAG
,
"unknow action"
+
" isLeftRight = "
+
isLeftRight
);
}
if(distance >= MAXRANGDISTANCE){ disInRang = false; }else{ disInRang = true;//距离传感器被遮挡 } if(Settings.System.getInt(mContext.getContentResolver(),POCKET_MODE, 1) == 1 && isRing){//开关打开并且响铃 if(disInRang && isPocket && !mActFlag){ mActFlag = true; previousMuteMode = am.getRingerMode(); am.setRingerMode(AudioManager.RINGER_MODE_NORMAL); previousRing = am.getStreamVolume(AudioManager.STREAM_RING );//获取铃声大小 am.setStreamVolume(AudioManager.STREAM_RING,am.getStreamMaxVolume(AudioManager.STREAM_RING), AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE);//设置为最大铃声 Log.d(TAG, "set max ring = "+am.getStreamMaxVolume(AudioManager.STREAM_RING)+" current ring = "+previousRing);
} }else if(!disInRang && mActFlag){ mActFlag = false; am.setRingerMode(previousMuteMode);//恢复之前铃声 am.setStreamVolume(AudioManager.STREAM_RING,previousRing, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); Log.d(TAG, "set back current dddaf ring = "+previousRing); }else if(mActFlag){ mActFlag = false; am.setRingerMode(previousMuteMode);//恢复之前铃声 am.setStreamVolume(AudioManager.STREAM_RING,previousRing, AudioManager.FLAG_REMOVE_SOUND_AND_VIBRATE); Log.d(TAG, "set back current thie swatch is close ring = "+previousRing); }
}
};
TelecomManager
getTelecommService
()
{
if
(
mContext
!=
null
)
return
(
TelecomManager
)
mContext
.
getSystemService
(
Context
.
TELECOM_SERVICE
);
return
null
;
}
public
void
tearDown
()
{
mAudioModeProvider
.
removeListener
(
this
);
mAccelerometerListener
.
enable
(
false
);
mDisplayListener
.
unregister
();
turnOffProximitySensor
(
true
);
//取消注册监听加速度传感器
if
(
mSensorManager
!=
null
){
mSensorManager
.
unregisterListener
(
mGsensorListener
);
mSensorManager
=
null
;
}
}