android按鍵精靈。C++編寫。-創(chuàng)新互聯(lián)

可以記錄屏幕鍵盤等傳感器對(duì)系統(tǒng)的輸入。android按鍵精靈。C++編
寫。

上一篇文章做的那個(gè)稍微有點(diǎn)復(fù)雜了,還需要把板子的輸出拿回電腦處理再倒回去。這個(gè)就簡(jiǎn)單多了用法如下

建網(wǎng)站原本是網(wǎng)站策劃師、網(wǎng)絡(luò)程序員、網(wǎng)頁設(shè)計(jì)師等,應(yīng)用各種網(wǎng)絡(luò)程序開發(fā)技術(shù)和網(wǎng)頁設(shè)計(jì)技術(shù)配合操作的協(xié)同工作。創(chuàng)新互聯(lián)專業(yè)提供成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司,網(wǎng)頁設(shè)計(jì),網(wǎng)站制作(企業(yè)站、響應(yīng)式網(wǎng)站建設(shè)、電商門戶網(wǎng)站)等服務(wù),從網(wǎng)站深度策劃、搜索引擎友好度優(yōu)化到用戶體驗(yàn)的提升,我們力求做到極致!

usage:
event record /path/file1
event replay /path/file1

給我女友寫的程序直接搬過來了,所以注釋有些冗余。

"stdafx.h"

#include <sys/types.h>
#include<sys/stat.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
#include<fcntl.h>
#include<sys/ioctl.h>
#include<errno.h>
#include<asm/types.h>
#include<unistd.h>
#include<iostream>
#include<vector>
struct input_event {
    timeval time;
    __u16 type;
    __u16 code;
    __s32 value;
};
struct myinputevent:public input_event
//繼承了16字節(jié)的數(shù)據(jù)結(jié)構(gòu),添加了一個(gè)deviceID{
int deviceID;

};

main.cpp

#include "stdafx.h"void record(char* filename);
void replay(char* filename);
int main(int argc, char *argv[])
{
if(argc!=3 || (strcmp(argv[1],"record") & strcmp(argv[1],"replay")))
    {
        std::cout<<

  "usage:"<<std::endl<<
  "event record /path/file1"<<std::endl<<
  "event replay /path/file1"<<std::endl;
return 0;
    }
if(!strcmp(argv[1],"record"))
        record(argv[2]);
else
        replay(argv[2]);
return 0;
}

replay.cpp

#include "stdafx.h"http://#define DEBUGint timedif(timeval& a,timeval& b)
//這是個(gè)計(jì)算時(shí)間差的函數(shù),對(duì)于一個(gè)timeval的數(shù)據(jù)結(jié)構(gòu),前面4字節(jié)秒,后面4字節(jié)微秒
//這個(gè)函數(shù)接受兩個(gè)這樣的結(jié)構(gòu),返回一個(gè)微秒單位的時(shí)間差{
return (b.tv_sec-a.tv_sec)*1000000+(b.tv_usec-a.tv_usec);
}


void replay(char* filename)
{

int fi = open(filename,O_RDONLY);
if(fi==-1)
    {
        std::cout<<filename<<" cannot be opened"<<std::endl;
        exit(0);
    }


char dev[40]="/dev/input/eventX";


int DeviceFile[10];
for(char i='0';i<='9';++i)
    {
        dev[16]=i;
int f=open(dev,O_RDWR);
//把所有的event都打開準(zhǔn)備寫入        DeviceFile[i-'0']=f;
//把句柄保存下來,如果打不開的話f值是-1#ifdef DEBUG
if(f!=-1)
            std::cout<<"Device opened:"<<i<<std::endl;
#endif

    }
    myinputevent event0,event1;
    read(fi,&event0,sizeof(myinputevent));
//先讀取第一個(gè)event到event0中    timeval timetemp=event0.time;
//臨時(shí)存儲(chǔ)event中的時(shí)間,因?yàn)橥O(shè)備寫的時(shí)候,時(shí)間要清空    memset(&event0.time, 0, sizeof(struct timeval));
//清空時(shí)間    write(DeviceFile[event0.deviceID], &event0.time, sizeof(input_event));
//寫回設(shè)備    event0.time=timetemp;
//把剛剛保存的時(shí)間拿回來  while(read(fi,&event1,sizeof(myinputevent)))
//只要文件還能讀,就讀取下一個(gè)event到event1中    {

int sleeptime=timedif(event0.time,event1.time);
//計(jì)算event0和event1的時(shí)間差#ifdef DEBUG
        std::cout<<"sleep"<<sleeptime<<std::endl;
#endif
        usleep(sleeptime);
//進(jìn)行時(shí)間間隔        event0.time=event1.time;
//把event1的時(shí)間賦值給event0,這樣下次循環(huán)的時(shí)候繼續(xù)對(duì)比下一個(gè)時(shí)間差        memset(&event1.time, 0, sizeof(struct timeval));
//清空event1的時(shí)間        write(DeviceFile[event1.deviceID], &event1.time, sizeof(input_event));
//把event1寫回設(shè)備    }
for(int i=0;i<=9;++i)
    {
if(DeviceFile[i]!=-1)
            close(DeviceFile[i]);
//關(guān)閉所有設(shè)備
    }
    std::cout<<"Replay completed"<<std::endl;
}

record.cpp

#include "stdafx.h"#define DEBUG
inlinebool eventcmp(const myinputevent& a,const myinputevent& b)
//這個(gè)比較函數(shù)為了之后排序用,因?yàn)閮蓚€(gè)自定義的數(shù)據(jù)結(jié)構(gòu),你用標(biāo)準(zhǔn)排序函數(shù),排序肯定不知道你這倆結(jié)構(gòu)應(yīng)該怎么比大小
//定義了我的數(shù)據(jù)結(jié)構(gòu)之間如果做小于比較時(shí),時(shí)間小就算小。
//這樣就可以采用標(biāo)準(zhǔn)排序函數(shù)對(duì)事件進(jìn)行排序了。{
if(a.time.tv_sec<b.time.tv_sec)
return 1;
if(a.time.tv_sec>b.time.tv_sec)
return 0;
if(a.time.tv_usec<b.time.tv_usec)
return 1;
else   return 0;
}



std::vector<myinputevent> AllRecordedEvent;
//這里有個(gè)數(shù)組,用來添加所有錄制到的eventchar fn[200];
void afterstop(int x)
//按下ctrl+c和回車之后,錄制停止,做數(shù)據(jù)整理和保存工作
//主要是按時(shí)間順序?qū)κ录判?,然后保存{
#ifdef DEBUG
    std::cout<<"Recorded events:"<<AllRecordedEvent.size()<<std::endl;
#endif
    std::cout<<"Sorting & saving..."<<std::endl;
    std::stable_sort(AllRecordedEvent.begin(),AllRecordedEvent.end(),eventcmp);
    std::cout<<"Sort completed"<<std::endl;
//這是排序語句,對(duì)所有的錄制的event排序,排序時(shí)大小比較用eventcmp函數(shù),也就是根據(jù)時(shí)間先后排序啦
//因?yàn)橛械臅r(shí)候,設(shè)備的輸出并不按照時(shí)間順序,比如你按開機(jī)鍵,它涉及的不止一個(gè)event,有時(shí)會(huì)有微微的時(shí)間上的錯(cuò)序
//任何錯(cuò)序都會(huì)嚴(yán)重影響replay,所以這里必須排序啦,這里一定要stable_sort,也就是排序必須是穩(wěn)定的
//對(duì)于不穩(wěn)定的排序,有時(shí)兩個(gè)事件的時(shí)間完全相等,可能會(huì)使原來在后面的跑前面去  int f=open(fn,O_WRONLY | O_CREAT | O_TRUNC);
if(f==-1)
    {
        std::cout<<fn<<" cannot be opened!";
        exit(0);
    }
//打開一開始event record file中那個(gè)file文件進(jìn)行寫入  for(unsigned int i=0;i<AllRecordedEvent.size();++i)
    {
        write(f,&AllRecordedEvent[i],sizeof(myinputevent));
    }
    close(f);
    std::cout<<"Record completed. Filename:"<<fn<<std::endl;
    exit(0);
}
void record(char* filename)
{
    std::cout<<"If using windows adb, you have to "busybox stty intr ^X" to change the INTR from Ctrl-C to Ctrl-X"<<std::endl;
    std::cout<<"And the stop recording command will be ctrl-X."<<std::endl
<<"If using linux adb, you are fine."<<std::endl;
//注意如果用windows中的adb,按下ctrl+c之后windows的shell也會(huì)收到命令從而終止adb shell,這樣達(dá)不到終止錄制的功能
//所以如果非要在windows中使用adb,就需要用這個(gè)命令busybox stty intr ^X,把板子的終止組合鍵注冊(cè)到ctrl-X上去
//這樣按ctrl-X再回車,就可以終止錄制    strcpy(fn,filename);
int f=open(fn,O_WRONLY | O_CREAT);
//先嘗試打開一下參數(shù)中的文件,若失敗就不繼續(xù)了  if(f==-1)
    {
        std::cout<<fn<<" cannot be opened!";
        exit(0);
    }
    close(f);
struct sigaction act;
    act.sa_handler=afterstop;
    sigemptyset(&act.sa_mask);
    act.sa_flags= 0;
    sigaction(SIGINT,&act, NULL);
//這里注冊(cè)了ctrl+c事件,這樣錄制過程中按下ctrl+c然后回車,可以執(zhí)行afterstop函數(shù)。  char dev[40]="/dev/input/eventX";

int DeviceFile[10];
for(char i='0';i<='9';++i)
    {
        dev[16]=i;
int f=open(dev,O_RDONLY | O_NONBLOCK);
//把所有的event都打開,這樣保證能包括鍵盤和屏幕
//這里O_RDONLY是只讀,O_NONBLOCK是非阻塞。非阻塞的意思就是讀取的時(shí)候,如果設(shè)備里沒有,就返回-1。
//如果是阻塞的話,設(shè)備里沒有,read函數(shù)是不返回的,要等到有了才返回。
//所以阻塞肯定不行,因?yàn)槲矣幸欢言O(shè)備要循環(huán)讀取的,如果第一個(gè)設(shè)備沒數(shù)據(jù)就會(huì)卡住,后面的設(shè)備都讀不到。        DeviceFile[i-'0']=f;
//把句柄保存下來,如果打不開的話f值是-1#ifdef DEBUG
if(f!=-1)
            std::cout<<"Device opened:"<<i<<std::endl;
#endif

    }
char buffer[2048];


    std::cout<<"Recording started, press Ctrl+C then press ENTER to stop recording"<<std::endl;

while(1)
    {
for(int i=0;i<10;++i)
        {
if(DeviceFile[i]==-1)
continue;
int ReadSize=read(DeviceFile[i],buffer,2048);
//不斷的循環(huán),把打開了的文件反復(fù)讀取,這里緩存區(qū)必須是16的倍數(shù),因?yàn)樯傻臄?shù)據(jù)是16字節(jié)的數(shù)據(jù)結(jié)構(gòu),這個(gè)基本結(jié)構(gòu)不能破壞了
//16字節(jié)的數(shù)據(jù)結(jié)構(gòu)中,前4字節(jié)是秒,然后4字節(jié)微秒,最后8字節(jié)是實(shí)際的設(shè)備發(fā)送的信息
//這里read會(huì)返回讀取到的字節(jié)數(shù)量,如果啥也沒讀到會(huì)返回-1 if(ReadSize!=-1)
            {
#ifdef DEBUG
                std::cout<<"device"<<i<<"read"<<ReadSize<<std::endl;
#endif  for(input_event *p=(input_event*)buffer;(char*)p<buffer+ReadSize;++p)
                {
                    myinputevent my;

                    my.code=p->code;
                    my.type=p->type;
                    my.value=p->value;
                    my.time=p->time;
                    my.deviceID=i;
                    AllRecordedEvent.push_back(my);
//這里可能難理解,buffer里存儲(chǔ)了大量16字節(jié)的event,所以讓指針p是數(shù)據(jù)結(jié)構(gòu)指針,然后16字節(jié)16字節(jié)的挪動(dòng)
//我有一個(gè)自己的數(shù)據(jù)結(jié)構(gòu)叫myinputevent,比這個(gè)16字節(jié)來說,尾部添加了一個(gè)4字節(jié)的int,存儲(chǔ)設(shè)備的event號(hào)
//你可以在stdafx.h中看到這些數(shù)據(jù)結(jié)構(gòu)
//把那16字節(jié)的原封不動(dòng)的放到我的數(shù)據(jù)結(jié)構(gòu)中,再把我自己的設(shè)備號(hào)賦值,就完成了這一個(gè)事件的錄制。
//然后就存儲(chǔ)到AllRecordedEvent里面去。                }
            }
        }
    }

}

新聞標(biāo)題:android按鍵精靈。C++編寫。-創(chuàng)新互聯(lián)
轉(zhuǎn)載來源:http://bm7419.com/article30/iiipo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供服務(wù)器托管App設(shè)計(jì)、ChatGPT、響應(yīng)式網(wǎng)站、域名注冊(cè)、網(wǎng)站收錄

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

商城網(wǎng)站建設(shè)