最近忙得很
公司裁员,然后合并事业部,最近忙得很。最终还是没有把我裁掉,没能如愿,只能辞职了。辞职的话就不有赔偿了。
合并以后,已经打乱了我的节奏了。同学们应该也发现,我很少有发动态有更新内容了,实在是忙呀。
计划是15号辞职,一个月后走人。什么年假呀,13薪就不要了。
正题
客户需要一个功能,在相机界面的时候,按下power按键,进行拍照,而不是熄屏。
同样的,另外一个客户是需要在拍照界面按power按键不能熄屏,因为熄屏录制是违法行为嗷。
怎么实现呢?
思路
首先,按键处理,我们在PhoneWindowManager里修改。
思路就是,当我们知道相机现在是活跃的,那么我们就把这个power按键转成音量减按键。
同学们都知道吧,android原生相机按音量减按键是会拍照的
问题点来了,怎么知道相机的状态呢 ?
这里就涉及到一个通讯的问题了,我们可以用广播,用AIDL,可以用内容提供者,也可以用属性值。
这里面我使用属性值比较方便。但是,属性值的写入,有权限限制,因此我不在应用层的调用去修改状态。
而是在frameworks层去更新相机的状态。
实现
- 相机状态变更
- 按键转换
相机状态变更
我打算在frameworks/base/services/core/java/com/android/server/camera
目录下的CameraServiceProxy.java
private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
@Override
public void pingForUserUpdate() {
notifySwitchWithRetries(30);
}
@Override
public void notifyCameraState(String cameraId, int newCameraState, int facing,
String clientName) {
String state = cameraStateToString(newCameraState);
String facingStr = cameraFacingToString(facing);
Slog.v(TAG, "Camera " + cameraId + " facing " + facingStr + " state now " +
state + " for client " + clientName);
//对状态进行判断,然后修改状态即可
if("CAMERA_STATE_OPEN".equals(state)){
SystemProperties.set("persist.sys.camera_state","1");
}else if("CAMERA_STATE_CLOSED".equals(state)){
SystemProperties.set("persist.sys.camera_state","0");
}
updateActivityCount(cameraId, newCameraState, facing, clientName);
}
};
我修改了这个属性值persist.sys.camera_state
如果相机打开了,那么就修改为1,否则就为0
处理按键
状态有变化了,那么我们在PhoneWindowManager.java
里处理按键事件
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
低版本的可能在其他目录,自己搜索一下就能找到。
private void powerPress(long eventTime, boolean interactive, int count) {
if (mScreenOnEarly && !mScreenOnFully) {
Slog.i(TAG, "Suppressed redundant power key press while "
+ "already in the process of turning the screen on.");
return;
}
BackToLaunchFactoryTest=false;
if (count == 2) {
powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
} else if (count == 3) {
powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
} else if (count == 6) {
BackToLaunchFactoryTest=true;
BackToLaunchFactoryTest_time=eventTime;
//launchFactoryTest(0);
} else if (interactive && !mBeganFromNonInteractive) {
String topActivity = getTopActivity();
String isCameraOpen = SystemProperties.get("persist.sys.camera_state","idel");
Slog.d(TAG,"isCameraOpen ==> " + isCameraOpen);
//如果当前是相机界面,打开相机
Slog.d(TAG,"topActivity ====> " + topActivity);
if("com.android.camera.CameraActivity".equals(topActivity)||
"com.android.camera.CameraLauncher".equals(topActivity)||
"com.boll.wrongquescard.ui.TakePhotoActivity".equals(topActivity)||
"1".equals(isCameraOpen)){
//拍照
Slog.d(TAG,"拍照吧,皮卡丘....");
//转成25号按键,就可以拍照
try{
Instrumentation inst = new Instrumentation();
inst.sendKeyDownUpSync(KeyEvent.KEYCODE_VOLUME_DOWN);
}catch (Exception e) {
Log.e("Exception when onBack", e.toString());
}
return;
}
switch (mShortPressOnPowerBehavior) {
case SHORT_PRESS_POWER_NOTHING:
break;
case SHORT_PRESS_POWER_GO_TO_SLEEP:
goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
goToSleep(eventTime, PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
launchHomeFromHotKey();
break;
case SHORT_PRESS_POWER_GO_HOME:
shortPressPowerGoHome();
break;
case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
if (mDismissImeOnBackKeyPressed) {
if (mInputMethodManagerInternal == null) {
mInputMethodManagerInternal =
LocalServices.getService(InputMethodManagerInternal.class);
}
if (mInputMethodManagerInternal != null) {
mInputMethodManagerInternal.hideCurrentInputMethod();
}
} else {
shortPressPowerGoHome();
}
break;
}
}
}
Slog.i(TAG, "powerkey BackToLaunchFactoryTest "+BackToLaunchFactoryTest);
}
看我注释就知道了,如果是相机打开了,直接把按键转成KeyEvent.KEYCODE_VOLUME_DOWN
Instrumentation
注意导包
import android.app.Instrumentation;
okay,到这里就可以完成这个功能了。
重点是思路,避开权限,通讯选择简单的属性值。
一边是写入状态,一边是读取状态。
还有就是按键转换。
拍照输出
keycode is == > 26
is down == > false
Receive Input KeyEvent of Powerkey up, interactive=true
isCameraOpen ==> 1
topActivity ====> com.android.camera.CameraActivity
拍照吧,皮卡丘....
keycode is == > 25
is down == > true
keycode is == > 25
is down == > false
状态是对的
当我退出拍照界面时的日志输出
keycode is == > 26
is down == > false
Receive Input KeyEvent of Powerkey up, interactive=true
isCameraOpen ==> 0
topActivity ====> com.android.launcher3.Launcher
Started going to sleep... (why=2)
到此,拍照也是成功的。