MAUI開發Android程序使PDA掃碼廣播消息轉發至Web頁面

前言

公司系統的手持終端(PDA)是用的Vue寫的前端代碼
在PDA上用瀏覽器直接打開Web頁面
PDA掃碼的時候,輸出模式直接用模擬鍵盤按鍵的方式輸出
這樣在Web頁面上,如果一個輸入框在當前有焦點的情況下
PDA掃碼的內容會直接填充至對應的輸入框
正常的話這樣沒有問題

但是最近有一個項目,PDA不是我們提供。
而是使用現有PDA,要把我們的系統在現有PDA上使用
但是現有PDA使用的掃碼輸出方式是用的Andorid廣播

因爲現有PDA不只有我們一家系統,所以不能修改掃碼輸出方式
這樣就使得我們不得不對系統進行改造


思考方法

因爲系統已經使用Vue框架已經開發好的。不可能爲了這麼點事情
把PDA上的系統全用Android重新來開發一次,那樣成本太大

所以想的辦法也很簡單。
就是做一個Andorid的程序套殼,然後在程序裏使用WebView加載現有系統
這樣在Andorid程序裏接收PDA掃碼的廣播信號
然後收到信號後,把掃碼到的內容使用WebView的JavaScript調用方式
傳輸到Web頁面接收。
這樣就實現了在Web頁面上接收Andorid的廣播消息功能

實現過程

因爲我們沒有Andorid的開發人員,
只有前端的NodeJs和後端的.Net開發人員
所以開發Android程序框架也很自然
只能是.Net開發人員使用 Xamarin.Android 或者 MAUI 這兩種方式

因爲只是一個Android的程序套殼,界面也不是很難
所以就當一次小試驗,自然也就想嘗試一下微軟最新的MAUI了

安裝MAUI

因爲我們原來開發沒有使用過MAUI,雖然機器上有VS2022
但是也要添加MAUI的開發功能
安裝MAUI參考鏈接

創建MAUI應用

參照微軟的文檔一步步操作創建MAUI應用
創建MAUI應用參考鏈接

在主界面添加WebView

WebView參考文檔

我們設置WebView的瀏覽地址爲我們系統的Web地址
此處設置爲:http://10.76.99.70:8081/

把MainPage.xaml文件修改如下

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="WMS.RFWrap.MainPage">

    <ScrollView>
        <StackLayout>
            <WebView x:Name="mainWeb" Source="http://10.76.99.70:8081/" VerticalOptions="FillAndExpand"></WebView>
        </StackLayout>
    </ScrollView>

</ContentPage>

接收Android廣播消息

在Platforms.Andorid目錄下創建廣播消息接收代碼
其中,IntentFilter設置的值要與PDA上配置的廣播消息代碼一至

namespace WMS.RFWrap.Platforms.Android;

[BroadcastReceiver(Enabled = true, Exported = true)]
[IntentFilter(new[] { "android.intent.ACTION_DECODE_DATA" })]
public class ScanBroadcastReceiver : BroadcastReceiver
{
    private Action<string> ScanDataAccepted;
    public ScanBroadcastReceiver()
    {

    }
    public ScanBroadcastReceiver(Action<string> action)
    {
        this.ScanDataAccepted = action;
    }
    public override void OnReceive(Context context, Intent intent)
    {
        var value = intent.GetStringExtra("barcode_string");
        ScanDataAccepted?.Invoke(value);
    }
}

在Platforms.Andorid.MainActivity.cs文件註冊廣播接收

public class MainActivity : MauiAppCompatActivity
{
    public ScanBroadcastReceiver scanReceiver { get; set; }
    /// <summary>
    /// 委託事件
    /// </summary>
    public static Action<string> ScanDeviceRecevied;
    protected override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        scanReceiver = new ScanBroadcastReceiver((barcode) =>
        {
            ScanDeviceRecevied?.Invoke(barcode);
        });
    }
    protected override void OnResume()
    {
        base.OnResume();
        RegisterReceiver(scanReceiver, new Android.Content.IntentFilter("android.intent.ACTION_DECODE_DATA"));
    }
    protected override void OnPause()
    {
        UnregisterReceiver(scanReceiver);
        base.OnPause();
    }
}

在MainPage.xaml.cs文件裏編寫接收代碼
接收到廣播掃碼內容後,通過WebView的Eval方法來執行Web頁面方法
我們這裏使用的是window.postMessage協議通訊
window.postMessage參考文檔
我們調用postMessage方法,把內容傳輸到Web頁面

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
#if ANDROID
        //var mainActivity = Platform.CurrentActivity as MainActivity;
        MainActivity.ScanDeviceRecevied = (barcode) => {
            Console.WriteLine(barcode);
            OnScanBarcode(barcode);
        };
#endif
    }
    public void OnScanBarcode(string barcode)
    {
        if (mainWeb != null)
        {
            var data = new { type = "barcode", data = barcode };
            var json = JsonSerializer.Serialize(data);
            var script = $"postMessage({json},'*')";
            mainWeb.Eval(script);
        }
    }
}

在前端Vue頁面接收WebView傳過來的postMessage信號
因爲我們使用的是postMessage信號,所以在前端只要監聽message事件就可以了
message事件與Vue無關,所有Web頁都可以使用
然後在onScanMsg回調方法裏面處理對應的數據,就能正常接收信息了
window.addEventListener('message', onScanMsg)

<template>
  <router-view />
</template>

<script>
import { provide, ref, reactive, toRaw, onMounted, onUnmounted } from 'vue'
import { useStore } from 'vuex'
export default {
  setup() {
    const store = useStore() //使用store
    onMounted(() => {
      window.addEventListener('message', onScanMsg)
    })
    const onScanMsg = (e) => {
      console.log('onScanMsg', e)
      if (typeof e.data === 'object' && e.data.type === 'barcode')
        store.commit('SET_SCANCODE', e.data.data)
    }
    return {}
  }
}
</script>

<style>
</style>

本示例是接收到信息後,通過vuex設置全局Store值
這樣在要獲取掃碼的頁面只用監聽Store值變化,就可以接收到最新的掃碼結果

<template>
  <van-nav-bar title="掃碼" left-text="數據" left-arrow fixed placeholder @click-left="$router.replace({ path: '/Home/DataIndex' })" />
  <van-field v-model="scancode" label="數據" placeholder="請掃碼" />
  <van-list>
    <van-cell-group>
      <van-cell v-for="item in list" :key="item" :title="item" />
    </van-cell-group>
  </van-list>
</template>

<script>
import { defineComponent, reactive, ref, toRefs, toRaw, onMounted, watch, computed, getCurrentInstance } from 'vue'
import { useStore } from 'vuex'
export default {
  setup() {
    const store = useStore()//使用store
    const scancode = computed(() => store.getters.scancode)
    const list = ref([])
    watch(() => store.getters.scancode, (newValue) => {
      list.value.push(newValue)
    })
    return {
      scancode,
      list
    }
  }
}
</script>

<style>
</style>

最終實現結果

強烈建議PDA設備廠商把 PDA廣播信號 集成至 WebView

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章