One-click photo, one-click video:
(S version)
First, do logical processing on the corresponding key-value logic
base/services/core/java/com/android/server/policy/PhoneWindowManager.java
case KeyEvent.KEYCODE_CAMERA:{// take photo
if (down) {
if(getCurrentActivityName().equals("com.freeme.factory.input.KeyboardTest")){
break;
} else if(!getCurrentActivityName().contains("com.mediatek.camera")) {
Intent intent;
if (keyguardActive) {
//intent = newIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
intent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE);
intent.putExtra("takePhoto","1");
} else {
//intent = newIntent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
intent = newIntent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra("takePhoto","1");
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivityAsUser(intent,UserHandle.CURRENT_OR_SELF);
}
}
break;
}
case KeyEvent.KEYCODE_F3:{//yantao takevideo
if (down) {
if(getCurrentActivityName().equals("com.freeme.factory.input.KeyboardTest")){
break;
} else if (!getCurrentActivityName().contains("com.mediatek.camera")){
Intent intent = newIntent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra("takeVideo","1");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
startActivityAsUser(intent,UserHandle.CURRENT_OR_SELF);
}
}
break;
}
private String getCurrentActivityName() {
ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> taskInfo =am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
android.util.Log.i("yantao","currentActivity name=="+componentInfo.getClassName());
return componentInfo.getClassName();
}
Then change it in the camera app
vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/CameraActivity.java
private staticfinal int DELAY_MSG_ONE_CLICK_CAMERA_FLAG = 100;
Add at the end of protected voidonResumeTasks() {
Intent intent =getIntent();
String takeVideo=intent.getStringExtra("takeVideo");
String takePhoto=intent.getStringExtra("takePhoto");
if(takeVideo != null || takePhoto !=null){
if("1".equals(takeVideo) ||"1".equals(takePhoto))
mMainHandler.sendEmptyMessageDelayed(DELAY_MSG_ONE_CLICK_CAMERA_FLAG,500);
}
在privateHandler mMainHandler = new Handler() {
join case
case DELAY_MSG_ONE_CLICK_CAMERA_FLAG:
mCameraAppUI.triggerShutterButtonClick(-1);
break;
What is called here is not the application of the camera itself, but a separate activity inside, so add the flag to prevent Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS from being displayed in the background, so that the user can only click the button to enter.
There is a bug like this: when the screen is locked, clicking the camera will jump to the default interface of the camera and then take a picture, but the interface of the video cannot be pressed, and the video interface will be displayed after unlocking, but there is no recording
Notice! ! ! ! ! If the delay made by this delay is too short, the interface UI will not be functional. For example, if the old version below is used for 0.5 seconds, the function will have problems, and it will be normal if it is used for 1 second.
(Take O version as an example)
O version needs to change the logic in cameraactivity, because there is no triggerShutterButtonClick, this method needs to use the click method of photo and video respectively
Still in src/com/android/camera/CameraActivity.java
private staticfinal int DELAY_MSG_ONE_CLICK_PHOTO_FLAG = 100;
private static final intDELAY_MSG_ONE_CLICK_VIDEO_FLAG = 200;
Intent intent =getIntent();
String takeVideo=intent.getStringExtra("takeVideo");
String takePhoto=intent.getStringExtra("takePhoto");
android.util.Log.i("yantao","takeVideo=="+takeVideo+"\ntakePhoto=="+takePhoto);
if(takeVideo != null || takePhoto !=null){
if("1".equals(takeVideo) && takePhoto == null){
android.util.Log.i("yantao","cameraactivitytakeing");
mMainHandler.sendEmptyMessageDelayed(DELAY_MSG_ONE_CLICK_VIDEO_FLAG,1000);
}
if(takeVideo == null &&"1".equals(takePhoto)){
android.util.Log.i("yantao","cameraactivitytakeing");
mMainHandler.sendEmptyMessageDelayed(DELAY_MSG_ONE_CLICK_PHOTO_FLAG,1000);
}
}
case DELAY_MSG_ONE_CLICK_PHOTO_FLAG:
mModuleManager.onPhotoShutterButtonClick();
break;
case DELAY_MSG_ONE_CLICK_VIDEO_FLAG:
mModuleManager.onVideoShutterButtonClick();
break;
Notice! ! !
If you want to meet the requirement of automatically exiting after taking a photo or recording a video, modify it as follows:
Roughly the same as above. You need to add another handler, because clicking the ok button to save the picture also takes time to wait for the ui,
private HandlermHandler;
Example in resume
mHandler = newHandler();
Finally in caseDELAY_MSG_ONE_CLICK_PHOTO_FLAG:
join one
mHandler.postDelayed(newRunnable() {
public void run() {
mModuleManager.onOkButtonPress();
}
}, 1000);
One-button recording, press the button again to stop recording and then save and exit:
Cameraactivity does not need to be changed, and a button logic needs to be added to the corresponding shutter processing
For example, the O version is in
src/com/mediatek/camera/mode/VideoMode.java
protectedboolean onKeyDown(int keyCode, KeyEvent event) {
Join, this F4 is our physical button for one-click recording,
caseKeyEvent.KEYCODE_F4:
onBackPressed();
mActivity.finish();
break;
This return operation is because the source code is designed, and it can be saved after returning, just call this method
protectedboolean onBackPressed() {
Log.d(TAG, "[onBackPressed()]CurrentModeState " + getModeState());
if (ModeState.STATE_IDLE ==getModeState()) {
return false;
}
if (ModeState.STATE_RECORDING ==getModeState()) {
stopVideoRecordingAsync(true);
}
return true;
}
After saving, it will return to the option of × or √, but it has actually been saved at this time, so you only need to delete it in finish at the end
One-click recording:
base/services/core/java/com/android/server/policy/PhoneWindowManager.java
Key handling:
case KeyEvent.KEYCODE_F2:{ //yantao record
if(getTopActivityPacakgeName().equals("com.freeme.factory")
||getCurrentActivityName().contains("com.android.soundrecorder")) {
break;
}
if (down) {
Intent intent = new Intent();
intent.setClassName("com.android.soundrecorder","com.android.soundrecorder.SoundRecorder");
intent.putExtra("takeRecord","1");
SystemProperties.set("persist.sys.record.taking","1");
startActivityAsUser(intent,UserHandle.CURRENT_OR_SELF);
}else if (event.getAction() ==KeyEvent.ACTION_UP) {
}
break;
}
The attribute persist.sys.record.taking is added here to judge that the recorder entered by each key has the recording function. If it is entered from the recent background, it will still be the previous activity. If it is not judged, it will still have the function.
Here we use the S version of the recorder that comes with the source code as an example:
vendor/mediatek/proprietary/operator/packages/apps/SoundRecorder/OP01/src/com/android/soundrecorder/SoundRecorder.java
private staticfinal int DELAY_MSG_ONE_CLICK_RECORD_FLAG = 100;
Add at the end of protected void onResume() {
Intent intent =getIntent();
if(android.os.SystemProperties.get("persist.sys.record.taking","0").equals("1")){
String takeRecord=intent.getStringExtra("takeRecord");
if(takeRecord != null){
if(takeRecord.equals("1")){
android.util.Log.i("yantao","takeRecordin");
mHandler.sendEmptyMessageDelayed(DELAY_MSG_ONE_CLICK_RECORD_FLAG,100);
android.os.SystemProperties.set("persist.sys.record.taking","0");
}
}
}
Processing in handler
private HandlermHandler = new Handler() {
add case
case DELAY_MSG_ONE_CLICK_RECORD_FLAG:
onClickRecordButton();
break;
Notice! ! !
The click event cannot be used directly, otherwise it will not succeed! ! ! Handler is required for asynchronous processing,
Avoid directly processing transactions in the UI main thread and causing other processing work that affects the UI main thread. Take this recorder as an example. If you directly do a click event, the mService is empty, indicating that the main thread is not ready yet, which is normal. So you need to use a handler for asynchronous processing. In fact, the delay here can not directly sendEmptyMessage
sendMessage(Messagemsg)
sendEmptyMessage(int what)
In fact, these two methods are the same, one is to pass message type msg, the other is to pass int type what, if you pass what, it will eventually be converted to msg
Handler basic usage:
import android.os.Handler;
mHandler.sendEmptyMessageDelayed(int,100);
private HandlermHandler = new Handler() {
@Override
public void handleMessage(Message msg){
switch(msg.what) {
case int:
break;
default:
break;
}
}
};
want to remove this message
mHandler.removeMessages(int);
handler.removeMessages(0); is a match
mHandler.postDelayed(new Runnable() {
public void run() {
}
},1000);
The whole handler does delay processing, handler.removeMessages(0); cancels the post operation
MediaStore.ACTION_IMAGE_CAPTURE,MediaStore.ACTION_IMAGE_CAPTURE_SECURE
Just take a picture, the jumping interface cannot record video, and exit after taking a picture
MediaStore.ACTION_VIDEO_CAPTURE, also can only record
MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA and MediaStore.ACTION_IMAGE_CAPTURE_SECURE are direct access to the camera
Intent.FLAG_ACTIVITY_NEW_TASK
To start an Activity outside of the Activity context, you need to set the FLAG_ACTIVITY_NEW_TASK flag to the Intent, otherwise an exception will be reported.
.Add this flag, if you jump to the Activity in the same application, no new Task will be created, only when you jump in a different application will a new Task be created
Intent..FLAG_ACTIVITY_CLEAR_TOP
Destroy the target Activity and all activities above it, and recreate the target Activity
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
If set, new activities will not be saved in the list of recently started activities. J means that you can’t see the background in recent, but in fact there are still, but it will be cleared after a while
Intent.FLAG_ACTIVITY_SINGLE_TOP
Same function as loading mode singleTop
Stack top reuse (when the started Activity is at the top of the Task stack, it can be reused and directly calls the onNewIntent method)
General use combination
setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP)
The Activity with the three modes of singleTop, singleTask, and singleInstance is set. If a new Activity page is opened, the same instance on the top of the stack will be reused, and a new instance will not be recreated. After the Activity is reused, it will call onNewIntent(Intent intent) method.
intent.setFlags is to replace the original flag, addFlags is to add the flag on the original basis