Android N版本 三指截屏

首先自己恭喜自己找到新的工作,这段时间也把自己的写过的一些功能做个总结。
手势快捷操作现在很多手机厂商都有做,三指截屏只是一个例子,可以通过这个例子去实现某个操作<->某个动作。本文只是写个简单的需求,后期可能自己扩展,例如像OPPO系统的上三指分屏,下三指截图。

一:修改的文件如下

M alps/frameworks/base/api/current.txt
M alps/frameworks/base/api/system-current.txt
M alps/frameworks/base/api/test-current.txt
M alps/frameworks/base/core/java/android/provider/Settings.java
M alps/frameworks/base/core/java/android/view/ViewGroup.java
M alps/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
M alps/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
M alps/frameworks/base/packages/SystemUI/AndroidManifest.xml
M alps/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
M alps/packages/apps/Settings/AndroidManifest.xml
A alps/packages/apps/Settings/res/drawable-xhdpi/ic_settings_three_screenshot.png
M alps/packages/apps/Settings/res/values-zh-rCN/strings.xml
M alps/packages/apps/Settings/res/values/strings.xml
M alps/packages/apps/Settings/src/com/android/settings/Settings.java
M alps/packages/apps/Settings/src/com/android/settings/SettingsActivity.java
A alps/packages/apps/Settings/src/com/android/settings/fuzhu/ThreeScreenShot.java
修改文件分类
1)frameworks/base/
2)packages/apps/Settings/
这个博客主要记录frameworks/base/相关的修改与实现 Settings模块的修改可以参考我从前的博客
Android N Settings实战开发(1)一,二级界面增加
https://blog.csdn.net/qq_24716151/article/details/78619044
Android N Settings实战开发(2)一级界面状态更新
https://blog.csdn.net/qq_24716151/article/details/78675743

二:实现原理

实现原理:
1)Settings中开关控制状态,
Settings.System.putInt(getActivity().getContentResolver(), Settings.System.SCREENSHOTPOINTER, 1);
0代表关,1代表开。
2)ViewGroup.java中的事件分发中增加parse3PointerScreenShot(ev)手势判断逻辑

public boolean dispatchTouchEvent(MotionEvent ev) {
            if (mInputEventConsistencyVerifier != null) {
                mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
            }
            parse3PointerScreenShot(ev);
            Log.i("WHB11111","parse3PointerScreenShot-----PWM=");   
            ........
        }

3)parse3PointerScreenShot(ev)手势逻辑判断,如果符合逻辑发送截屏广播

private void parse3PointerScreenShot(MotionEvent ev) {
        int actionMasked = ev.getActionMasked();
        int pointerCount = ev.getPointerCount();

        //获取Settings中是否允许三指截屏,1为允许,非1为不允许
        //最好是在framework中加入
        int value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.SCREENSHOTPOINTER, 0);
        Log.i("WHB11111","SCREENSHOTPOINTER="+value);
        if (value != 1) {
            return ;
        }

        if (pointerCount == 3) {
            switch (actionMasked) {
            case MotionEvent.ACTION_POINTER_DOWN:
                for (int i = 0; i < pointerCount; i++) {
                    int pointerId = ev.getPointerId(i);
                    downY[pointerId] = ev.getY(i);
                }
                is3Pointer = true;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                if (is3Pointer) { 
                    //如果是三个手指,就获取每个手指的滑动间距,否则就清空数据
                    for (int i = 0; i < pointerCount; i++) {
                        int pointerId = ev.getPointerId(i);
                        upY[pointerId] = ev.getY(i);
                        matchY[pointerId] = Math.abs(upY[pointerId] - downY[pointerId]);
                    }
                } else {
                    clearArrayData(downY);
                    clearArrayData(upY);
                    clearArrayData(matchY);
                }
                break;

            default:
                break;
            }

            boolean[] flag = new boolean[] {
                    false, false, false,
            };

            for (int i = 0; i < pointerCount; i++) {
                int pointerId = ev.getPointerId(i);
                //三个手指划过的距离是否大于最大预定值
                if (matchY[pointerId] > Y_OFFSET) {
                    flag[i] = true;
                    matchY[pointerId] = 0;
                }
            }

            //如果三个指头都划过了最大预定值,就开始截屏
            if (flag[0] && flag[1] && flag[2]) {
                Intent intent = new Intent("com.whb.screenshot");
                //Send broadcast to PhoneWindowManager to cature screen
                getContext().sendBroadcast(intent);
                Log.d(TAG, "Intercept the key Three finger to capture screen"); 
            }
        } else {
            is3Pointer = false;
        }
    }

4)PhoneWindowManager接收广播实现截屏操作
注册广播

        filter = new IntentFilter("com.whb.screenshot");
        context.registerReceiver(mScreenShotReceiver, filter);

接收广播通过调用SystemUI的截图方法实现截图操作

    BroadcastReceiver mScreenShotReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            if ("com.qucii.screenshot".equals(intent.getAction())) {
                Log.i("WHB11111","begin-----SCREENSHOTPOINTER=");
                mHandler.post(mScreenshotRunnable); // 调用系统代码,执行截屏逻辑
            }
        }
    };

如果想调用SystemUI的截图方法,要做如下修改

--- a/alps/frameworks/base/packages/SystemUI/AndroidManifest.xml
+++ b/alps/frameworks/base/packages/SystemUI/AndroidManifest.xml

         <service android:name=".screenshot.TakeScreenshotService"
             android:process=":screenshot"
-            android:exported="false" />
+            android:exported="true" />

         <!-- Called from PhoneWindowManager -->
         <receiver android:name=".screenshot.ScreenshotServiceErrorReceiver"

三:解决ListView事件冲突

public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.isFromSource(InputDevice.SOURCE_MOUSE)
                && ev.getAction() == MotionEvent.ACTION_DOWN
                && ev.isButtonPressed(MotionEvent.BUTTON_PRIMARY)
                && isOnScrollbarThumb(ev.getX(), ev.getY())) {
            return true;
        }
+       if (ev.getPointerCount()==3
+               &&Settings.System.getInt(mContext.getContentResolver(), +Settings.System.SCREENSHOTPOINTER, 0)==1) {
+           return true;
+           }
        return false;
    }

四:默认状态控制

1.frameworks/base/packages/SettingsProvider/res/values/defaults.xml设置默认指控制三指截屏操作是默认开还是关。
M alps/frameworks/base/core/java/android/provider/Settings.java
M alps/frameworks/base/packages/SettingsProvider/res/values/defaults.xml
M alps/frameworks/base/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
Settings.java

+          public static final String SCREENSHOTPOINTER = "screenshot_pointer";

DatabaseHelper.java

+          loadIntegerSetting(stmt, Settings.System.SCREENSHOTPOINTER,
+                                       R.integer.screenshot_pointer);

defaults.xml

+         <integer name="screenshot_pointer">0</integer>

2.编译遇到不过的时候

******************************
You have tried to change the API from what has been previously approved.
To make these errors go away, you have two choices:
    1) You can add "@hide" javadoc comments to the methods, etc. listed in the
      errors above.

    2) You can update current.txt by executing the following command:
         make update-api
      To submit the revised current.txt to the main Android repository,
      you will need approval.
******************************

执行make update-api,并把相关的current.txt提交上

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值