駕駛培訓APP流程圖一(讀取IC卡流程)

背景

全志平臺Android4.4系統
公司原有的wince顯示屏已經不能滿足公司業務需求,使用android系統開發我司下一代產品。
由於android系統功能強大,可應用的範圍不止步於顯示屏一個產品。爲考慮產品的可維護性,現重新設計一套系統框架,以滿足開發項目的需求。

架構圖

MMCU在這裏插入圖片描述

描述

考過駕照的都知道一套流程,科目二科目三是需要上傳學時的,到省平臺審覈到學時到一定時長才能預約考試

主要制定了和終端MCU模塊的通信,以及按照省平臺的要求和平臺進行tcp的通信。
本篇着重描述MUC通信過程

代碼走向

myApp-----------
動態註冊一個廣播MyReceiver ,同時另一個App發送MCU請求

IntentFilter updateIntent = new IntentFilter();
		updateIntent.addAction(ACTION_00_01);// mcu信息查詢
		updateIntent.addAction(ACTION_10_00);// 實時信息
		updateIntent.addAction(ACTION_10_17);// 讀取身份證
		updateIntent.addAction(ACTION_20_02);// 讀IC卡
		mCardBroadcast = new Hst55Receiver();
		registerReceiver(mCardBroadcast, updateIntent);
/* 打包發送 */
	public void handOutCommand(Context context) {
		Intent intent = new Intent();
		intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
		intent.setAction(Constant.MCU_SEND_ACTION);
		/*Log.i("MCUCMD","test_data");
		Log.i("MCUCMD",StringUtils.byteToString(readHead())+"\n"+GetCmdLen());
		for(byte b:readHead()){
			Log.i("MCUCMD",b+"");
		}*/
		intent.putExtra("size", GetCmdLen());
		intent.putExtra("data", readHead());
		intent.putExtra("reSend", reSend);
		context.sendBroadcast(intent, null);
	}

在一個app啓動時,也啓動了另外一個app的service

APPlication
if (isHst55Running == false) {
				CatchApplication.showLog("主界面啓動hst55");
				HelpFuns.StartExternalService(context, "com.hst.cz.hst55", "com.hst.cz.hst55.ServiceRun");
			}
 <service
            android:name="com.hst.cz.hst55.ServiceRun"
            android:exported="true" >//這屬性表明了支持另外的應用啓動這個服務
        </service>

恰好這個service裏面是動態的註冊了廣播MCU請求廣播

	try {
			getSerialPort();// 獲取端口
			mOutputStream = mSerialPort.getOutputStream();// 獲取輸出流
			mInputStream = mSerialPort.getInputStream();// 獲取輸入流
			/* Create a receiving thread */
			mReadThread = new ReadThread();// 創建線程
			mReadThread.start();// 開始運行
		} catch (SecurityException e) {
		} catch (IOException e) {
		} catch (InvalidParameterException e) {
		}
		if (mSerialPort != null) {
			IntentFilter filter = new IntentFilter();
			filter.addAction(Constant.MCU_SEND_ACTION); // 添加動態廣播的Action
			sendReceiver.setOutputStream(mOutputStream, getApplicationContext());
			registerReceiver(sendReceiver, filter);//然後,receiver接受到了MCU請求,開始和MCU模塊通信

		}

裏面的OutputStream是程序對mcu的寫入流

SerialPort
{
private FileOutputStream mFileOutputStream;

	public SerialPort(File device, int baudrate, int flags) 
	{
		/* Check access permission */
		if (!device.canRead() || !device.canWrite()) 
		{
			try 
			{
				/* Missing read/write permission, trying to chmod the file */
				Process su;
				su = Runtime.getRuntime().exec("/system/bin/su");
				String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
						+ "exit\n";
				su.getOutputStream().write(cmd.getBytes());
				
				if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) 
				{
					throw new SecurityException();
				}
			}
			catch (Exception e) 
			{
				e.printStackTrace();
				throw new SecurityException();
			}
		}
		mFd = open(device.getAbsolutePath(), baudrate, flags);//這個open方法是通過jni訪問底層MCU
		if (mFd == null) 
		{
			Log.e(TAG, "native open returns null");
//			throw new IOException();
		}
		mFileInputStream = new FileInputStream(mFd);
		mFileOutputStream = new FileOutputStream(mFd);
	}
}

service也會開啓線程來輪詢MCU發回來的信息

private class ReadThread extends Thread {
		@Override
		public void run() {
			super.run();
			byte[] buffer = new byte[2048];
			int size = 0;
			byte[] bufferTemp = new byte[2048];
			int sizeTemp = 0;
			while (!isInterrupted())// 串口如果有數據
			{
				try {
					if (mInputStream == null)
						return;
					sizeTemp = mInputStream.read(bufferTemp, 0, 2000);// 讀取
					if (sizeTemp > 0) {
						if (size + sizeTemp <= buffer.length) {
							System.arraycopy(bufferTemp, 0, buffer, size, sizeTemp);
							size += sizeTemp;
							onDataReceived(buffer, size);// 轉發
							size = 0;
						} else {
							size = 0;
						}
					}
				} catch (IOException e) {
					e.printStackTrace();
					return;
				}
			}
		}
	}

也會開啓線程來給最初調用最初的app註冊的接收者

	new Thread() {
			public void run() {
				while (true) {
					while (comCmdArray.size() > 0) {
						McuCmd tmp = comCmdArray.get(0);
						if (tmp != null) {
							handOutCommand(tmp);//發送廣播
						}
						comCmdArray.remove(0);
					}
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}.start();

請求App的MyReceiver的定義如下

public class Hst55Receiver extends BroadcastReceiver {
	private static HandleCmdMcu handleCmdMcu = new HandleCmdMcu();

	@Override
	public void onReceive(Context context, Intent intent) {
		handleCmdMcu.putIntent(intent, context);
	}
}
public void putIntent(Intent intent, Context context) {
		int size = intent.getIntExtra("size", 0);
		if (size > 0) {
			setContext(context);
			McuCmd cmd = new McuCmd();
			byte hp[] = intent.getByteArrayExtra("data");
			cmd.initStmCmd(hp, size);
			McuHandleCmd(cmd);//從這裏即開始了接口回調
		}
	}

接口回調


	/*
	 * 電源設備管理
	 */
	private void getCardInfo(McuCmd cmd) {
		GetCardInfo.getCardInfo(context, cmd);
		if (mGetCardInfoLintener != null) {
			mGetCardInfoLintener.getCardInfo();
		}
	}

	@Override
	public void McuHandleCmd(McuCmd cmd) {
		switch (cmd.GetSubOrder()) {
		case 0x02: {
			getCardInfo(cmd);
		}
			break;
		}
	}

UI界面在回調,顯示卡片信息

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