模拟点击的方法实现视频监控功能(完整版)

125 篇文章 0 订阅
29 篇文章 0 订阅

对房屋等进行视频监控有较大的需求,现在手机较多,怎么样用手机去作为监控器实现这个功能呢?

目前市面上有些应用有这个功能,我试用了一些,有的很费电,需要一直保持摄像状态。

还有就是数据安全性,用户的隐私视频数据存在泄漏的风险。

比较便捷的一种方法是使用微信作为视频工具,需要查看的时候,向采集视频的手机发送视频请求,这样就可以随时进行连接查看,很省电,不必一直打开采集端。 

充分利用微信,就像借居蟹利用海螺一样



现在的问题是,如何让手机自动接听视频通话请求? 
微信视频请求只需要点击接听按钮,怎样去实现自动点击屏幕呢?

查找资料发现,adb shell input tap X Y 就可以实现点击 
X Y 为坐标数值。 
现在考虑写一个服务,简单点处理吧,接收SCREEN_ON广播,当手机屏幕亮的时候,就点击屏幕上指定的一个点,来进行模拟点击,实现接通视频。

尝试在代码中使用调用 
Runtime.getRuntime().exec(“input tap 322 667”); 
但是发现,不能够跨进行去进行点击,只能在启动服务的应用里进行点击。 
04-29 13:44:47.922: W/InputDispatcher(1092): Permission denied: injecting event from pid 12694 uid 10164 to window Window{ed6134b u0 com.*} owned by uid 10063 
04-29 13:44:47.922: W/InputManager(1092): Input event injection from pid 12694 permission denied.

查询资料, 
把手机root后 
Process process = Runtime.getRuntime().exec(“su”);

    OutputStream outputStream = process.getOutputStream();
    DataOutputStream dataOutputStream = new DataOutputStream(
         outputStream);
    dataOutputStream.writeBytes(cmd);
    dataOutputStream.flush();
    dataOutputStream.close();
    outputStream.close();

Android 6的手机上测试,报错 
04-28 16:36:40.487: W/System.err(21863): Java.io.IOException: Error running exec(). Command: [su] Working Directory: null Environment: null 
04-28 16:36:40.487: W/System.err(21863): at java.lang.ProcessManager.exec(ProcessManager.java:211) 
04-28 16:36:40.487: W/System.err(21863): at java.lang.Runtime.exec(Runtime.java:174) 
04-28 16:36:40.487: W/System.err(21863): at java.lang.Runtime.exec(Runtime.java:247) 
04-28 16:36:40.487: W/System.err(21863): at java.lang.Runtime.exec(Runtime.java:190) 
04-28 16:36:40.487: W/System.err(21863): at com.example.myservice.MyService.execShellCmd(MyService.java:38) 
04-28 16:36:40.487: W/System.err(21863): at com.example.myservice.MyService.access$0(MyService.java:34)

在Android 6的adb shell中,su命令识别不了。

看来root手机的方式有些问题, 
还是考虑直接采用 
Runtime.getRuntime().exec(“input tap 322 667”);的方式。

对于Input event injection from pid 12694 permission denied的问题 
网上有方法说是要增加权限,在系统源码里进行编译。

这里采用另一种方式,考虑屏蔽系统里的这个权限判断。

查看log 
find . -name *.java | xargs grep ‘Input event injectio’ 
搜索得到InputManagerService.java

private boolean injectInputEventInternal(InputEvent event, int displayId, int mode) { 
if (event == null) { 
throw new IllegalArgumentException(“event must not be null”); 

if (mode != InputManager.INJECT_INPUT_EVENT_MODE_ASYNC 
&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH 
&& mode != InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT) { 
throw new IllegalArgumentException(“mode is invalid”); 
}

    final int pid = Binder.getCallingPid();
    final int uid = Binder.getCallingUid();
    final long ident = Binder.clearCallingIdentity();
    final int result;
    try {
        result = nativeInjectInputEvent(mPtr, event, displayId, pid, uid, mode,

搜索nativeInjectInputEvent 
find . -name .c|xargs grep ‘nativeInjectInputEvent’

./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp:static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */, 
./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp: { “nativeInjectInputEvent”, “(JLandroid/view/InputEvent;IIIIII)I”, 
./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp: (void*) nativeInjectInputEvent },

vi ./frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

static jint nativeInjectInputEvent(JNIEnv* env, jclass /* clazz */,

        jlong ptr, jobject inputEventObj, jint displayId, jint injectorPid, jint injectorUid,

        jint syncMode, jint timeoutMillis, jint policyFlags) {

    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);

 

    if (env->IsInstanceOf(inputEventObj, gKeyEventClassInfo.clazz)) {

        KeyEvent keyEvent;

        status_t status = android_view_KeyEvent_toNative(env, inputEventObj, & keyEvent);

        if (status) {

            jniThrowRuntimeException(env, "Could not read contents of KeyEvent object.");

            return INPUT_EVENT_INJECTION_FAILED;

        }

 

        return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(

                & keyEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,

                uint32_t(policyFlags));

    } else if (env->IsInstanceOf(inputEventObj, gMotionEventClassInfo.clazz)) {

        const MotionEvent* motionEvent = android_view_MotionEvent_getNativePtr(env, inputEventObj);

        if (!motionEvent) {

            jniThrowRuntimeException(env, "Could not read contents of MotionEvent object.");

            return INPUT_EVENT_INJECTION_FAILED;

        }

 

        return (jint) im->getInputManager()->getDispatcher()->injectInputEvent(

                motionEvent, displayId, injectorPid, injectorUid, syncMode, timeoutMillis,

                uint32_t(policyFlags));

    } else {

        jniThrowRuntimeException(env, "Invalid input event type.");

        return INPUT_EVENT_INJECTION_FAILED;

    }

}

 

查看

frameworks\native\services\inputflinger\InputDispatcher.cpp

 

int32_t InputDispatcher::injectInputEvent(const InputEvent* event, int32_t displayId,

        int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis,

        uint32_t policyFlags) {

 

ALOGD("=====<<<<<>>>>>5-4 policyFlags |= POLICY_FLAG_TRUSTED");

//    if (hasInjectionPermission(injectorPid, injectorUid)) {

        policyFlags |= POLICY_FLAG_TRUSTED;

//    }

 

 

bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {

//test 

ALOGD("hasInjectionPermission called");

return true;

//    return injectorUid == 0

//            || mPolicy->checkInjectEventsPermissionNonReentrant(injectorPid, injectorUid);

}

 

这样就可以进行跨进程,跨页面进行点击了


在源码中编译ap来获得系统权限也可以实现,这个方式适用性更好

http://blog.csdn.net/aaajj/article/details/51464190

把服务的userId改成系统级别的,在Androidmanifest加上:

 <manifest xmlns:android="http://schemas.android.com/apk/res/android"

    android:sharedUserId="android.uid.system" >

编译后即可
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值