Skip to content

加载dex包

euxcet edited this page Mar 17, 2022 · 3 revisions

安卓应用使用情境包有直接导入和动态加载dex两种方式。直接导入库的使用方式十分普遍,在此不再赘述。动态加载dex包的做法是在应用运行时通过网络下载情境包编译得到的dex文件,并利用反射来实例化情境包中的类,完成对情境包的调用。

DataCollection.contextaction.ContextActionLoader中实现了对情境包的实例化,主要功能为控制情境识别的开始与关闭、向情境包输入数据、处理情境包的请求。

动态加载dex包的方式有一定的局限性,应用无法直接使用包内的类,如果包中某函数的输入或输出是一个包内部的类,在应用中只能用繁琐的反射来获取结果。同时应用无法实例化包内部的接口,这使得回调的实现变得困难。我们给出的解决方式是在应用中额外导入一个库NcnnLibrary(名称可能被修改)来保存一些对包和应用都可见的类,这些类被用在包的输入和输出中,使得调用变得容易。NcnnLibrary中还保存着ncnn这个神经网络前向计算框架,其中的c++代码无法被放入dex包中。

启动情境包识别的示例代码如下:

ContextActionLoader loader = new ContextActionLoader(mContext, classLoader);

// TapTapAction
ActionConfig tapTapConfig = new ActionConfig();
tapTapConfig.setAction(BuiltInActionEnum.TapTap);
tapTapConfig.putValue("SeqLength", 50);
tapTapConfig.setSensorType(Arrays.asList(SensorType.IMU));

ActionListener actionListener = action ->
        mHandler.post(() -> Toast.makeText(mContext, action.getAction(), Toast.LENGTH_SHORT).show());

// ProximityContext
ContextConfig proximityConfig = new ContextConfig();
proximityConfig.setContext(BuiltInContextEnum.Proximity);
proximityConfig.setSensorType(Arrays.asList(SensorType.PROXIMITY));

// InformationalContext
ContextConfig informationalConfig = new ContextConfig();
informationalConfig.setContext(BuiltInContextEnum.Informational);
informationalConfig.setSensorType(Arrays.asList(SensorType.ACCESSIBILITY, SensorType.BROADCAST));

ContextListener contextListener = context ->
        mHandler.post(() -> Toast.makeText(mContext, context.getContext(), Toast.LENGTH_SHORT).show());

RequestListener requestListener = config -> handleRequest(config);
loader.startDetection(Arrays.asList(tapTapConfig), actionListener, Arrays.asList(proximityConfig, informationalConfig), contextListener, requestListener);

ContextConfig和ActionConfig用于配置需要识别的情境和动作,可配置的项包括内置情境和动作的名称、参数、原始数据类型列表。ActionListener和ContextListener为识别结果的回调。RequestListener用于处理包对应用中数据的请求,例如请求无障碍窗口信息。

Clone this wiki locally