后端前端企业应用【免费下载链接】GreaterWMSThis Inventory management system is the currently Ford Asia Pacific after-sales logistics warehousing supply chain process . After I leave Ford , I start this project . You can share your vacant warehouse space, use it for those in need, and generate income项目地址https://gitcode.com/gh_mirrors/gr/GreaterWMS点击查看免费下载本文以 GreaterWMS 开源仓库中内置的com-darryncampbell-cordova-plugin-intentIntentShim插件文档为骨架结合其 JavaScript 桥接层、Android 原生实现与仓库中 ScanAPP.vue 的真实调用代码系统讲解如何在 Cordova/Quasar 移动应用中收发 Android Intent并给出在仓储扫码枪如 Zebra/Symbol DataWedge场景下的完整实战方案。读完本文你将掌握该插件的全部 API 用法、参数含义、底层实现机制以及在 GreaterWMS 扫描 App 中的集成方式。插件定位Android Intent 机制的通用 shim 层IntentShim 是一个面向 Android 平台的 Cordova 插件它提供了一层“通用垫片general purpose shim”把 Android 原生的 Intent 机制发送与接收暴露给 JavaScript 层。插件在页面上下文中定义了一个全局对象window.plugins.intentShim所有 API 都挂载在该对象上可运行于任何 Android 设备。从源码结构看插件由三部分组成JS 桥接层IntentShim.js —— 定义IntentShim构造函数及全部 API通过cordova/exec与原生层通信最后挂载为window.plugins.intentShimAndroid 原生实现IntentShim.java —— 继承CordovaPlugin负责解析 JS 传来的 JSON 参数、构造并发送android.content.Intent以及把接收到的 Intent 序列化成 JSON 回传给 JS工程注册文件plugin.xml —— 声明 feature、intent-filter、权限、FileProvider 与 AndroidX 依赖。插件本身以 MIT 协议开源其代码部分借鉴了cordova-plugin-intentnapolitano与cordova-webintentchrisekelley两个 MIT 项目源码注释中保留了相应致谢见 IntentShim.java 中的 Credit 注释。安装与工程集成安装命令文档给出的安装命令按 Cordova 版本区分Cordova 7通过 git URL 安装cordova plugin add https://github.com/darryncampbell/darryncampbell-cordova-plugin-intent.gitCordova 7通过 npm 包名安装cordova plugin add com-darryncampbell-cordova-plugin-intent在 GreaterWMS 中该插件以本地插件形式随仓库分发位于 com-darryncampbell-cordova-plugin-intent 目录其 package.json 声明的版本为 2.1.0并已记录在 Cordova 插件清单 android.json 中对应 Android 平台的org.greaterwms.scanner.app应用。Android X 与 Android Support Library 的选择文档明确了两条版本线需要 Android X 支持时使用 2.x.x 及以上版本仓库内置的 2.1.0 即属于该线仍使用旧的 Android Support Library 时只能使用 1.3.x 版本。Android X 支持不只体现在依赖声明上插件还带了一个after_prepare钩子脚本 after_prepare.js每次构建 Android 平台后它都会检查platforms/android/gradle.properties若缺失则自动追加android.useAndroidXtrue与android.enableJetifiertrue两行配置从而保证 AndroidX 迁移在工程中生效。与 Camera 插件的安装顺序文档特别强调如果同时安装cordova-plugin-camera必须先安装 camera 插件再安装本插件“MUST install cordova-plugin-camera first”。原因是本插件会向AndroidManifest.xml合并 FileProvider 与相关权限安装顺序错误可能导致资源或权限合并冲突。plugin.xml 中注册的内容从 plugin.xml 可以看到插件在 Android 工程中实际注入了以下内容注册IntentShimfeature并设置onloadtrue插件随应用启动即加载保证广播接收器能力就绪向应用 Activity 合并一个自定义 action 为com.darryncampbell.cordova.plugin.intent.ACTION的 intent-filter声明READ_EXTERNAL_STORAGE与REQUEST_INSTALL_PACKAGES两个权限前者用于读取外部存储中的文件后者与安装 APK 场景相关注册自定义 FileProviderCordovaPluginIntentFileProviderauthority 为${applicationId}.darryncampbell.cordova.plugin.intent.fileprovider并引用provider_paths.xml资源文件声明 AndroidX 核心库依赖androidx.core:core:1.1.0。API 总览插件共暴露 8 个文档记录的 API另外 JS 层还提供若干扩展 API。先看整体一览API作用对应 Android 原生机制registerBroadcastReceiver为指定 filter 注册动态广播接收器Context.registerReceiverIntentFilterunregisterBroadcastReceiver注销全部已注册的广播接收器Context.unregisterReceiversendBroadcast发送一个广播 IntentContext.sendBroadcastonIntent获取并持续监听启动 Activity 的 IntentActivity.onNewIntent()startActivity启动一个新的 ActivityActivity.startActivitygetIntent获取启动本 Activity 的 IntentActivity.getIntent()startActivityForResult启动 Activity 并接收其返回结果Activity.startActivityForResultsendResult向启动方返回RESULT_OK并结束本 ActivityActivity.setResultActivity.finishJS 层在 IntentShim.js 中还额外定义了startService、onActivityResult、realPathFromUri以及RESULT_CANCELED(0)、RESULT_OK(-1) 两个结果常量这些在原生实现 IntentShim.java 中均有对应分支startService、onActivityResult、realPathFromUri说明是文档之外的扩展能力。registerBroadcastReceiver动态注册广播接收器基本用法window.plugins.intentShim.registerBroadcastReceiver(filters, callback);该函数为指定的过滤器列表注册一个动态广播接收器当任意过滤器命中的广播到达时回调函数被触发。文档示例注册了两个 actionwindow.plugins.intentShim.registerBroadcastReceiver({ filterActions: [ com.darryncampbell.cordova.plugin.broadcastIntent.ACTION, com.darryncampbell.cordova.plugin.broadcastIntent.ACTION_2 ] }, function(intent) { console.log(Received broadcast intent: JSON.stringify(intent.extras)); });底层实现filter 的三类参数与 keepCallback原生层 IntentShim.java 的execute(registerBroadcastReceiver, ...)分支会解析三类过滤器参数并依次填入IntentFilterfilterActions必填对应filter.addAction()为空会直接返回INVALID_ACTIONfilterCategories可选对应filter.addCategory()filterDataSchemes可选对应filter.addDataScheme()用于按 data scheme如http、file过滤源码注释提到这解决了 GitHub Issue 24 中关于 data scheme 过滤的需求。注册完成后插件以PluginResult.Status.NO_RESULT且setKeepCallback(true)的方式持有回调上下文callback context广播到达时通过newBroadcastReceiver()内部类把 Intent 转成 JSON 后持续推送到 JS 层实现“一次注册、多次接收”的实时推送语义。每个接收器与回调上下文的映射保存在receiverCallbacks这个MapBroadcastReceiver, CallbackContext中。unregisterBroadcastReceiver注销广播接收器基本用法window.plugins.intentShim.unregisterBroadcastReceiver();调用后所有通过registerBroadcastReceiver注册的接收器都会被注销此后不会再收到任何已注册过滤器的广播。原生层通过遍历receiverCallbacks逐个调用unregisterReceiver并清空映射实现unregisterAllBroadcastReceivers()方法。Android Quirks生命周期管理文档明确指出开发者有责任在应用进入后台background或回到前台foreground时按需调用 unregister/register。官方示例在应用收到pause事件时注销接收器bindEvents: function() { document.addEventListener(pause, this.onPause, false); }, onPause: function() { window.plugins.intentShim.unregisterBroadcastReceiver(); }这一模式在 GreaterWMS 的 ScanAPP.vue 中得到了完整落地onPause时注销、onResume时重新注册避免后台状态下持续接收广播造成资源浪费或误触发。sendBroadcast发送广播 Intent基本用法window.plugins.intentShim.sendBroadcast(action, extras, successCallback, failureCallback);发送一个指定 action 的 Android 广播 Intent。文档示例原文代码实为startActivity的调用形态其语义为“向指定 action 发送带随机数 extras 的广播”window.plugins.intentShim.sendBroadcast({ action: com.darryncampbell.cordova.plugin.intent.ACTION, extras: { random.number: Math.floor((Math.random() * 1000) 1) } }, function() {}, function() {alert(Failed to open URL via Android Intent)});底层实现原生层execute(sendBroadcast, ...)分支先通过populateIntent(obj, callbackContext)把 JSON 参数组装成android.content.Intent再调用cordova.getActivity().sendBroadcast(intent)。populateIntent是插件最核心的参数解析函数它支持下列字段actionIntent action 字符串typeMIME 类型与url同时存在时使用setDataAndTypeurlURI 数据当 Android NAPI 24及以上且以file://开头时会自动走remapUriWithFileProvider改用 FileProvider 生成 content URIremapUriWithFileProvider否则通过CordovaResourceApi.remapUri转换extras额外数据支持 String/Boolean/Integer/Long/Double 等基本类型嵌套 JSONObject 会被转换为 Bundle其中EXTRA_TEXT配合text/html类型用Html.fromHtml处理、EXTRA_STREAM支持以 URI 方式分享图片附件、EXTRA_EMAIL自动转成字符串数组、EXTRA_KEY_EVENT可构造 KeyEventcomponent显式 Intent 的目标组件需同时提供package与classpackage目标应用包名flagsIntent flag 数值数组逐个addFlagschooser传入后通过Intent.createChooser包装为选择器。组装完成后还会统一加上Intent.FLAG_GRANT_READ_URI_PERMISSION确保接收方能读取共享的 URI 数据。onIntent 与 getIntent读取启动 IntentonIntent映射 Android onNewIntentwindow.plugins.intentShim.onIntent(callback);onIntent返回启动 Activity 的 Intent并映射到 Android 的Activity.onNewIntent()方法。注册的回调在 Activity 被重新启动时被调用window.plugins.intentShim.onIntent(function (intent) { console.log(Received Intent: JSON.stringify(intent.extras)); });原生层onNewIntent(Intent)方法IntentShim.java有一个值得注意的细节如果 JS 层尚未注册onIntent回调原生层会把新 Intent 暂存到deferredIntent字段当 JS 层随后调用onIntent时插件会立刻把暂存的 Intent 补发出去并清空该字段。getIntent同样会优先消费deferredIntent其次才返回cordova.getActivity().getIntent()。这一机制保证了“Intent 先到、JS 回调后注册”的时序不会丢数据。Android Quirks启动模式 SingleTop / SingleTask文档说明默认情况下 Android 应用以SingleTop启动模式创建。若想改为SingleTask需要在config.xml中修改platform nameandroid ... preference nameAndroidLaunchMode valuesingleTask/ /platform两种模式的核心差异在于SingleTop下 Activity 已在栈顶时新 Intent 走onNewIntentSingleTask下系统会确保栈中只有一个任务实例其它实例被销毁并把 Intent 交给栈顶实例。选择哪种模式会影响onNewIntent的触发时机开发者需根据应用场景权衡。getIntent获取启动 Intentwindow.plugins.intentShim.getIntent(resultCallback, failureCallback);对应Activity.getIntent()返回启动本 Activity 的 Intent。文档示例window.plugins.intentShim.getIntent( function(intent) { console.log(Action JSON.stringify(intent.action)); var intentExtras intent.extras; if (intentExtras null) intentExtras No extras in intent; console.log(Launch Intent Extras: JSON.stringify(intentExtras)); }, function() { console.log(Error getting launch intent); });startActivity启动新 Activity基本用法window.plugins.intentShim.startActivity(params, successCallback, failureCallback);对应Activity.startActivity。文档给出两个典型示例——拉起地图与打开浏览器// 启动地图 window.plugins.intentShim.startActivity( { action: window.plugins.intentShim.ACTION_VIEW, url: geo:0,0?qLondon }, function() {}, function() {alert(Failed to open URL via Android Intent)} ); // 打开浏览器 window.plugins.intentShim.startActivity( { action: window.plugins.intentShim.ACTION_VIEW, url: http://www.google.co.uk }, function() {}, function() {alert(Failed to open URL via Android Intent)} );底层实现无处理者时的错误处理原生层startActivity(Intent, ...)方法IntentShim.java会先用intent.resolveActivityInfo(...)检查系统中是否存在能处理该 Intent 的应用若没有会向 JS 返回PluginResult.Status.ERROR从而触发failureCallback。这与文档示例中“Failed to open URL via Android Intent”的失败提示正好对应也是插件对“打开外部应用失败”场景的兜底设计。startActivityForResult 与 sendResultActivity 间往返传值startActivityForResultwindow.plugins.intentShim.startActivityForResult(params, resultCallback, failureCallback);对应Activity.startActivityForResult启动新 Activity 并把结果通过resultCallback返回。文档示例是选择 Android 联系人window.plugins.intentShim.startActivityForResult( { action: window.plugins.intentShim.ACTION_PICK, url: content://com.android.contacts/contacts, requestCode: 1 }, function(intent) { if (intent.extras.requestCode 1) { console.log(Picked contact: intent.data); } }, function() { console.log(StartActivityForResult failure); });原生实现中requestCode未显式给出时默认取 1插件通过cordova.setActivityResultCallback(this)接管结果回调并在 onActivityResult 中把requestCode、resultCode一并塞入返回 Intent 的 extras 后回传若用户取消导致 intent 为 null也会构造一个仅含 requestCode/resultCode 的空 Intent 返回保证回调不丢失。JS 层的onActivityResult(callback)是另一种接收结果的方式。sendResult向启动方回传结果window.plugins.intentShim.sendResult(args, callback);假设本应用是被startActivityForResult启动的sendResult会以Activity.RESULT_OK状态把args.extras中的数据返回给启动方然后调用finish()结束当前 Activity。Android Quirksargs与callback两个参数都必须提供不需要该功能时传空对象和空函数即可window.plugins.intentShim.sendResult({}, function() {});文档的完整示例演示了多种数据类型的回传window.plugins.intentShim.sendResult( { extras: { Test Intent: Successfully sent, Test Intent int: 42, Test Intent bool: true, Test Intent double: parseFloat(142.12) } }, function() { } );原生层execute(sendResult, ...)会遍历 extras 并依据 JSON 类型分别调用putExtra嵌套 JSONObject 转 Bundle随后setResult(Activity.RESULT_OK, result)再finish()完整对应文档描述。预定义常量插件在 JS 层预定义了以下常量定义见 IntentShim.js可直接用于构造 Intentwindow.plugins.intentShim.ACTION_SENDandroid.intent.action.SENDwindow.plugins.intentShim.ACTION_VIEWandroid.intent.action.VIEWwindow.plugins.intentShim.EXTRA_TEXTandroid.intent.extra.TEXTwindow.plugins.intentShim.EXTRA_SUBJECTandroid.intent.extra.SUBJECTwindow.plugins.intentShim.EXTRA_STREAMandroid.intent.extra.STREAMwindow.plugins.intentShim.EXTRA_EMAILandroid.intent.extra.EMAILwindow.plugins.intentShim.ACTION_CALLandroid.intent.action.CALLwindow.plugins.intentShim.ACTION_SENDTOandroid.intent.action.SENDTOwindow.plugins.intentShim.ACTION_GET_CONTENTandroid.intent.action.GET_CONTENTwindow.plugins.intentShim.ACTION_PICKandroid.intent.action.PICK此外 JS 层还定义了ACTION_INSTALL_PACKAGE、ACTION_UNINSTALL_PACKAGE、RESULT_CANCELED(0) 与RESULT_OK(-1)可用于安装/卸载应用与结果码判断。Intent 的 JSON 表示无论接收广播、接收启动 Intent 还是接收 Activity 结果原生层都会调用getIntentJson(Intent)IntentShim.java把 Android Intent 序列化为 JSON 对象回传给 JS包含以下字段typeMIME 类型extrasextras Bundle 递归转换成的 JSON 对象actionIntent actioncategoriescategory 集合flagsflag 整数值component目标组件datadata URI 字符串package目标包名clipItemsAndroid 4.4 且有 ClipData 时包含htmlText、intent、text、uri、type、extension的数组用于处理多内容分享场景。这也是开发者在回调中经常访问intent.extras、intent.action、intent.data的原因——它们直接对应原生 Intent 的同名字段。GreaterWMS 实战基于 IntentShim 的 Zebra DataWedge 扫码集成该插件在 GreaterWMS 中的核心应用场景是 ScanAPP.vue 的扫码页面通过 Intent 机制与 Zebra/Symbol 手持终端上的 DataWedge 服务通信把硬件扫码枪的条码数据实时送入 WebView。发送 DataWedge 命令sendBroadcastScanAPP.vue 中的sendCommand函数封装了对 DataWedge API 的广播命令发送把命令名与参数放进 extras并携带SEND_RESULT要求 DataWedge 返回执行结果function sendCommand (extraName, extraValue) { var broadcastExtras {} broadcastExtras[extraName] extraValue broadcastExtras.SEND_RESULT sendCommandResults window.plugins.intentShim.sendBroadcast({ action: com.symbol.datawedge.api.ACTION, extras: broadcastExtras }, function () { }, function () { } ) }基于此封装页面可以下发com.symbol.datawedge.api.SOFT_SCAN_TRIGGER软触发扫描、GET_VERSION_INFO查询 DataWedge 版本、SET_CONFIG配置扫描 profile包括把扫码结果以intent_output_enabledintent_action: com.zebra.cordovademo.ACTION的方式输出等命令。注册接收器接收扫码结果registerBroadcastReceiverScanAPP.vue 中注册了两个 action 的广播接收器function registerBroadcastReceiver () { window.plugins.intentShim.registerBroadcastReceiver({ filterActions: [ com.zebra.cordovademo.ACTION, com.symbol.datawedge.api.RESULT_ACTION ], filterCategories: [ android.intent.category.DEFAULT ] }, function (intent) { // 命令执行结果RESULT_INFO if (intent.extras.hasOwnProperty(RESULT_INFO)) { ... } // DataWedge 版本信息 if (intent.extras.hasOwnProperty(com.symbol.datawedge.api.RESULT_GET_VERSION_INFO)) { ... } // 扫描到的条码数据 else if (!intent.extras.hasOwnProperty(RESULT_INFO)) { barcodeScanned(intent, new Date().toLocaleString()) } } ) }其中barcodeScanned读取intent.extras[com.symbol.datawedge.data_string]并把条码写入隐藏输入框、触发input事件从而驱动 GreaterWMS 的扫码业务逻辑。这个例子同时用到了本文讲解的filterActions、filterCategories、extras 读取、生命周期注销等多个知识点是该插件在真实仓储项目中的完整范式。生命周期管理unregisterBroadcastReceiver如文档强调扫描页面在pause事件中调用unregisterBroadcastReceiver()、在resume事件中重新registerBroadcastReceiver()ScanAPP.vue确保后台不接收广播、回到前台时恢复扫码能力。注意事项与限制平台支持插件仅支持 Android 平台iOS 与其它平台无对应实现兼容性前提仓库内置版本为 2.1.0AndroidX 线要求工程启用 AndroidX钩子脚本会自动写入gradle.properties若项目仍使用 Android Support Library需要回退到 1.3.x 版本已测版本README 记录插件在 Cordova 6.5.0 与 Cordova Android 6.2.1 上完成测试在当前仓库环境中实际以 Cordova 工程插件形式随 app/src-cordova 分发使用权限要求读取外部存储 URIrealPathFromUri、file://分享需要READ_EXTERNAL_STORAGE权限插件会通过ActivityCompat.requestPermissions主动申请但未授权时相关 API 会直接报错开发者需在 JS 层处理失败回调时序注意registerBroadcastReceiver持久的回调keepCallback要求开发者自行管理注册/注销生命周期避免泄漏与重复接收onIntent与getIntent对deferredIntent的消费是单次的注册回调前到达的 Intent 只会被补发一次。赞分享后端前端企业应用【免费下载链接】GreaterWMSThis Inventory management system is the currently Ford Asia Pacific after-sales logistics warehousing supply chain process . After I leave Ford , I start this project . You can share your vacant warehouse space, use it for those in need, and generate income项目地址https://gitcode.com/gh_mirrors/gr/GreaterWMS点击查看免费下载相关推荐GreaterWMS 移动端启动画面插件深度解析cordova-plugin-splashscreen 版本演进、配置实战与源码剖析GreaterWMS 移动端启动画面插件深度解析cordova plugin splashscreen 版本演进、配置实战与源码剖析 GreaterWMS 的后端前端企业应用GreaterWMS 移动端屏幕常亮方案cordova-plugin-insomnia 插件原理与实战配置GreaterWMS 移动端屏幕常亮方案cordova plugin insomnia 插件原理与实战配置 导读 本文以 GreaterWMS 开源仓库中内置后端前端企业应用Android Sunflower深度链接导航组件与Intent处理Android Sunflower深度链接导航组件与Intent处理 项目概述 Android Sunflower是一个园艺应用展示了将基于视图的应用迁移到移动开发示例工程上一篇TanStack Table React 列定义基类型 AppColumnDefBase 深度解析预绑定 cell/header/footer 组件的类型增强机制下一篇TiXL 中 SelectFloatFromDict 算子完全指南从 Dict 字典中精准提取浮点值创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考