物理按键一键拍照,一键录像,一键录音

一键拍照,一键录像:

(S版本)

首先在对应的键值逻辑上做逻辑处理

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();
                                }

然后在相机应用里改

vendor/mediatek/proprietary/packages/apps/Camera2/host/src/com/mediatek/camera/CameraActivity.java

private staticfinal int DELAY_MSG_ONE_CLICK_CAMERA_FLAG = 100;

在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() {

加入case

case DELAY_MSG_ONE_CLICK_CAMERA_FLAG:
mCameraAppUI.triggerShutterButtonClick(-1);
break;

这里的调起的不是相机本身这个应用,是里面单独的activity,所以加flag不让显示在后台Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,这样用户就只能点击按键才能进入。

这样有个bug:锁屏的时候点击一键相机会跳到相机默认界面然后拍照,而视频的那个界面一键按不出来,等解锁之后才显示这个video界面但是没有录制

注意!!!!!这个delay做的延迟如果太短的话,界面ui没起来就不会有功能,比如说下面的老版本如果用0,5秒的话功能会有问题,用1秒就正常

(O版本为例)

O版本需要改动cameraactivity里面的逻辑,因为没有triggerShutterButtonClick,这个方法了,需要用到photo和video分别的click方法

还是在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;

注意!!!

如果要满足拍完照或者录完像自动退出的需求,修改如下:

大致和上面一样。需要再加一个handler,因为点击ok键保存图片也需要时间等ui,

private HandlermHandler;

在resume里实例

mHandler = newHandler();

最后在caseDELAY_MSG_ONE_CLICK_PHOTO_FLAG:

加入一个

                                mHandler.postDelayed(newRunnable() {
                                                        public void run() {
                                                        mModuleManager.onOkButtonPress();
                                                        }
                                                    }, 1000);

一键录像,再按一次按键就停止录像然后保存退出:

Cameraactivity的都一样不需要改,另外需要在对应的快门处理上加一个按键逻辑

比如O版本的在

src/com/mediatek/camera/mode/VideoMode.java

protectedboolean onKeyDown(int keyCode, KeyEvent event) {

加入,这个F4就是我们一键录像的物理按键,

                                caseKeyEvent.KEYCODE_F4:
                                                onBackPressed();
                                                mActivity.finish();
                                            break;

这个返回操作是由于源码就设计好了,返回就能保存,调用这个方法就行

protectedboolean onBackPressed() {

Log.d(TAG, "[onBackPressed()]CurrentModeState " + getModeState());

if (ModeState.STATE_IDLE ==getModeState()) {

return false;

}

if (ModeState.STATE_RECORDING ==getModeState()) {

stopVideoRecordingAsync(true);

}

return true;

}

保存完之后还是会回到那个×或√的选项,但此时其实已经保存了,所以只需要最后在finish掉

一键录音:

base/services/core/java/com/android/server/policy/PhoneWindowManager.java

按键处理:

    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;
            }

这里加入属性persist.sys.record.taking,是为了判断每次按键进入的录音机才有录音功能,如果从recent后台进入的话还是之前的activity,不判断的话依然会有功能。

这里用了源码自带的录音机S版本为例:

vendor/mediatek/proprietary/operator/packages/apps/SoundRecorder/OP01/src/com/android/soundrecorder/SoundRecorder.java

private staticfinal int DELAY_MSG_ONE_CLICK_RECORD_FLAG = 100;

在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");
              }
       }
       }

在handler处理

private HandlermHandler = new Handler() {

添加case

    case DELAY_MSG_ONE_CLICK_RECORD_FLAG:
                 onClickRecordButton();
                 break;

注意!!!

不能直接使用点击事件,不然无法成功!!!需要handler做异步处理,

避免直接在UI主线程中处理事务导致影响UI主线程的其他处理工作。那这个录音机为例,如果直接做点击事件的话,那个mService就是空,说明主线程还没准备好,原本是正常的。所以需要用handler做异步处理,这里的延时其实也可以不要直接sendEmptyMessage

sendMessage(Messagemsg)

sendEmptyMessage(int what)

其实这两个方法是一样一样的,一个传Message类型的msg,一个传int类型的what,传what的,最终会转为msg

Handler基本用法:

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;

}

}

};

想要移除该消息

mHandler.removeMessages(int);

handler.removeMessages(0);是配合

mHandler.postDelayed(new Runnable() {

public void run() {

}

},1000);

整个handler做延时处理,handler.removeMessages(0);就把post操作取消了

MediaStore.ACTION_IMAGE_CAPTURE,MediaStore.ACTION_IMAGE_CAPTURE_SECURE

只是单纯拍照,跳转的界面不能录像,且拍一张就退出了

MediaStore.ACTION_VIDEO_CAPTURE,也是只能录像

MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA和MediaStore.ACTION_IMAGE_CAPTURE_SECURE是直接进入相机

Intent.FLAG_ACTIVITY_NEW_TASK

在Activity上下文之外启动Activity需要给Intent设置FLAG_ACTIVITY_NEW_TASK标志,不然会报异常。

.加了该标志,如果在同一个应用中进行Activity跳转,不会创建新的Task,只有在不同的应用中跳转才会创建新的Task

Intent..FLAG_ACTIVITY_CLEAR_TOP

销毁目标Activity和它之上的所有Activity,重新创建目标Activity

FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

如果设置,新的Activity不会在最近启动的Activity的列表中保存。J就是recent里面看不到后台,但实际上还是有的,不过过一会会被清掉

  1. Intent.FLAG_ACTIVITY_SINGLE_TOP

  1. 与加载模式singleTop功能相同

  1. 栈顶复用(当被启动的Activity处于Task栈顶时,可以复用,直接调用onNewIntent方法)

一般用组合

setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TOP)

设置了singleTop、singleTask、singleInstance这三种模式的Activity,如果开启一个新的Activity页面,栈顶存在相同的实例就复用,都不会重新创建一个新实例,Activity复用后都会调用onNewIntent(Intent intent)方法。

intent.setFlags是替换原来的flag,addFlags是原有基础上添加flag

猜你喜欢

转载自blog.csdn.net/youthking1314/article/details/129622405