历数OpenMobile开发的一些坑
来源:互联网 发布:mac玩lol 编辑:程序博客网 时间:2024/05/15 09:08
因为OpenMobile不能向下兼容,各版本支持手机系统版本不同:
15 - API level 15, Android 4.0.316 - not available17 - API level 17, Android 4.218 - API level 18, Android 4.319 - API level 19, Android 4.420 - developer preview, not available21 - API level 21, Android 5.0
所以在开发时不能使用其中任一版本,使用任一版本将可能导致部分支持NFC手机无法使用应用,出现兼容性问题;
推荐做法是:通过配置使用手机系统自带OpenMobile库
配置流程为:
(1)准备某一版本OpenMobile API支撑库,导入项目libs,该支撑库只在编译期间使用,项目打包不将此包打入到项目里,
配置项为:(工具Android studio 中app->build.gradle中配置)
dependencies { compile fileTree(include: ['*.jar'], exclude: ['openMobileApi.jar'], dir: 'libs') compile 'com.android.support:appcompat-v7:23.4.0' compile 'com.google.code.gson:gson:2.8.0' compile 'com.squareup.okhttp3:okhttp:3.5.0' //provided表示只在编译时使用jar包,运行时默认环境中已经存在这个jar包了 //jar包在网上有下载,注意要与ROM版本一直,不要一味求最新 provided files('libs/openMobileApi.jar')}
(2)工程主配置文件AndroidManifest.xml配置使用系统自带OpenMobile库:
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.cosw"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="org.simalliance.openmobileapi.SMARTCARD" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.nfc" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:name="com.cosw.app.MyApplication" android:supportsRtl="true" android:theme="@style/AppTheme"> <!--true:使用系统自带OpenMobile库--> <uses-library android:name="org.simalliance.openmobileapi" android:required="true" /> <activity android:name="com.cosw.app.SplashActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application></manifest>
以上配置之后,即可实现编译期使用libs库,打包时使用系统自带库的目标。
二、使用OpenMObile API获取SWP卡ATR进行密钥分散时注意点
1、手机必须支持NFC
2、卡片放到手机里之后,手机会获取卡片ATR,并且保存到手机,此时手机是肯定拿到了ATR的,在此基础上通过openmobile API的session.getATR()可能存在以下两种情况
(1)使用openmobile API的session.getATR()获取ATR时,部分手机获取为null,也有的手机获取atr为全0(OPPO N5207支持NFC,但是ATR获取为全0000000000)
(2)同一张支持NFC的SWP卡,不同的手机获取的ATR不同,区别在于多了个TCK校验位(如果想忽略校验位,可以通过ATRParseUtil判断是否存在校验位,存在则去掉校验位。)
ATR格式说明参考:
说明文档:https://en.wikipedia.org/wiki/Answer_to_reset
ATR解析工具:http://ruimtools.com/atr.php
3、ATR:可以作为分散密钥的因子,主要用的是历史字节数进行分散。
4、通过手机自带的openmobile API去获取atr,同一张卡片可能获取的atr不同,不同之处在于ATR的校验位,该校验位有可能存在,也与可能不存在
示例:
ATR(TCK存在,需要校验,此时有的手机能拿到20校验位I,有的手机不行)
(和包UAT测试卡1)华为p10 ------atr=3B9F95803FC7A08031E073FE211B633A104E83009000
(和包UAT测试卡1)华为 honor ------atr=3B9F95803FC7A08031E073FE211B633A104E8300900020
(和包UAT测试卡1)中国移动M812C ------atr=3B9F95803FC7A08031E073FE211B633A104E8300900020
(蓝牙卡)atr:3B9194803FC3A0BC65
ATR(TCK不存在,不需要校验):3B9A96401E4100014308025054E20D
5、如果存在需要判断ATR是否存在校验位,存在则去掉校验位的需求,则可以参考下面代码:
package com.atr.test;/** * * @author Administrator ATR判断是否存在检验字节 参考:<br/> * (1)http://www.ruimtools.com/atr.php<br/> * (2)https://en.wikipedia.org/wiki/Answer_to_reset<br/> * ATR(TCK存在,需要校验,此时有的手机能拿到20校验位I,有的手机不行)<br/> * 华为p10 ------atr=3B9F95803FC7A08031E073FE211B633A104E83009000<br/> * 华为 honor ------atr=3B9F95803FC7A08031E073FE211B633A104E83009000 20<br/> * 中国移动M812C ------atr=3B9F95803FC7A08031E073FE211B633A104E83009000 20 * atr:3B9194803FC3A0BC65<br/> * ATR(TCK不存在,不需要校验):3B9A96401E4100014308025054E20D<br/> * */public class ATRParseUtil {public static void main(String[] args) {/*System.out.println(parseATR(StringUtil.hexStringToByteArray("3B9194803FC3A0BC65")));*/try {int atrZero=Integer.valueOf("0000000000");} catch (Exception e) {System.out.println("不为全0");}System.out.println("全0");}// 历史字节数private static int historical_len = 0;// 已经校验的字节数private static int info_recv_len = 1;public static String parseATR(byte[] atr) {//(1)部分支持NFC机型获取ATR为null,可能底层没有缓存卡片ATRif (atr == null || atr.length == 0) {return null;}//(2)ATR为全0也无法做个人化,代表机型://(1)OPPO N5207try {int atrZero=Integer.valueOf(StringUtil.byteArrayToHexString(atr));if(atrZero==0){System.out.println("获取ATR为全0,不支持"); return null;}} catch (Exception e) {}int ta_b = 0;int tb_b = 0;int tc_b = 0;int td_b = 0;int tck_exist = 0;int ta1_exist = 0;// 每次计算之前从新初始化historical_len = 0;info_recv_len = 1;info_recv_len++;ta_b = (atr[info_recv_len - 1] >> 4) & 0x01;tb_b = (atr[info_recv_len - 1] >> 5) & 0x01;tc_b = (atr[info_recv_len - 1] >> 6) & 0x01;td_b = (atr[info_recv_len - 1] >> 7) & 0x01;// 格式字节T0 在范围[0..15] 中以其4个低位(第4个MSbit到第1个LSbit)编码历史字节T i的数量K// 示例1:3B9194803FC3A0BC65:91->10010001 ,此时历史字节数为1// 示例2:3B9F95803FC7A08031E073FE211B633A104E8300900020:9F->10011111,,此时历史字节数为15historical_len = atr[info_recv_len - 1] & 0x0F;System.out.println(atr[info_recv_len - 1]);if (ta_b != 0) {ta1_exist = 1;}boolean flag = isTCKExist(ta_b, tb_b, tc_b, td_b, ta1_exist, tck_exist,atr);System.out.println("是否存在TCK校验位:" + flag);System.out.println("info_recv_len:" + info_recv_len);System.out.println("historical_len:" + historical_len);if (flag) {// 存在TCK校验位byte[] atrCopy = new byte[historical_len + info_recv_len];System.arraycopy(atr, 0, atrCopy, 0, atrCopy.length);return StringUtil.byteArrayToHexString(atrCopy);} else {// 不存在TCK校验位return StringUtil.byteArrayToHexString(atr);}}/** * 是否存在TCK校验位 * * @param ta_b * @param tb_b * @param tc_b * @param td_b * @param ta1_exist * @param tck_exist * @param atr * @return */private static boolean isTCKExist(int ta_b, int tb_b, int tc_b, int td_b,int ta1_exist, int tck_exist, byte atr[]) {if (ta_b != 0) {ta_b = 0;info_recv_len++;if (ta1_exist == 1) {ta1_exist = 0;}return isTCKExist(ta_b, tb_b, tc_b, td_b, ta1_exist, tck_exist, atr);} else if (tb_b != 0) {tb_b = 0;info_recv_len++;return isTCKExist(ta_b, tb_b, tc_b, td_b, ta1_exist, tck_exist, atr);} else if (tc_b != 0) {tc_b = 0;info_recv_len++;return isTCKExist(ta_b, tb_b, tc_b, td_b, ta1_exist, tck_exist, atr);} else if (td_b != 0) {td_b = 0;info_recv_len++;System.out.println("td_b:"+ StringUtil.byteToHexString(atr[info_recv_len - 1]));System.out.println("td_b:" + atr[info_recv_len - 1]);ta_b = (atr[info_recv_len - 1] >> 4) & 0x01;tb_b = (atr[info_recv_len - 1] >> 5) & 0x01;tc_b = (atr[info_recv_len - 1] >> 6) & 0x01;td_b = (atr[info_recv_len - 1] >> 7) & 0x01;System.out.println(atr[info_recv_len - 1] & 0x0F);if ((atr[info_recv_len - 1] & 0x0F) != 0x00)tck_exist = 1;return isTCKExist(ta_b, tb_b, tc_b, td_b, ta1_exist, tck_exist, atr);}return tck_exist != 0 ? true : false;}}
参考链接:
https://github.com/seek-for-android/pool/wiki/UsingSmartCardAPI
https://stackoverflow.com/questions/32438584/open-mobile-api-with-android-21
http://www.jianshu.com/p/a3a3b3db6b37
NFC读取sim卡之建立卡连接:http://blog.csdn.net/qq_24224369/article/details/52371153
检查手机是否连接网络,sim的存在以及是否支持NFC功能:http://blog.csdn.net/qq_24224369/article/details/52693454
7816 ATR解析工具:http://www.ruimtools.com/atr.php
ATR应答重置:https://en.wikipedia.org/wiki/Answer_to_reset
SIMalliance OMAPI transport test plan介绍之二接口规范篇:http://www.51testing.com/html/36/489136-831212.html
openmobile api:http://seek-for-android.github.io/javadoc/V4.0.0/org/simalliance/openmobileapi/package-summary.html
sim卡与短信息:http://www.ithao123.cn/content-170384.html
- 历数OpenMobile开发的一些坑
- 历数CSS缩写的一些好处
- 历数CSS缩写的一些好处
- 历数C#的设计错误
- OpenMobile ACL可让MeeGo兼容所有的Android程序
- 历数史上死于“如厕”的帝王!!!!!!!!!
- 历数25个最损的中文网站
- 历数两年内的重大空难事故
- 历数我用过的手机
- 历数那些失败的项目(1)---M...
- 历数那些失败的项目(3)---Nutch...
- 历数那些失败的项目(5)---AnyTips
- Sun中国工程研究院院长历数Solaris开发一百单八将!
- 历数云计算为安全带来的七大利好
- 历数那些失败的项目(2)---S-Quicktake
- 历数那些失败的项目(4)---CMS网站
- 【pyhton学习笔记】历数那些遇到的错误
- React实战-历数一个混乱React项目的罪状
- 突破!中兴新支点Linux桌面操作系统在龙芯CPU上支持QQ使用
- 全栈式PHP集成环境-laragon(二) 配置、使用
- MUI:mui项目中如何使用原生JavaScript代替jquery来操作dom
- 新一线城市“抢人”大战:多地加快推进户籍改革
- mysql直接导出查询数据到excel
- 历数OpenMobile开发的一些坑
- Amap/google[高德和谷歌]地图加载不出来,【问题总汇】-持续更新...
- webservice之实现一个基于JWS的webservice项目
- Java并发编程之重入锁
- 气球颜色统计 HDU-1004
- 创建Cocos2dx项目两种方法
- hadoop集群监控工具--ganglia的搭建(YUM的方式)
- C#操作WebApi(Sql参数化)
- C/C++常考笔试面试题