一、开发时配置应用程序使用手机系统自带的OpenMObile API库
因为OpenMobile不能向下兼容,各版本支持手机系统版本不同:

15 - API level 15, Android 4.0.3
16 - not available
17 - API level 17, Android 4.2
18 - API level 18, Android 4.3
19 - API level 19, Android 4.4
20 - developer preview, not available
21 - 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" /><applicationandroid: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-libraryandroid:name="org.simalliance.openmobileapi"android:required="true" /><activityandroid: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开发的一些坑相关推荐

  1. 【golang程序包推荐分享】分享亿点点golang json操作及myJsonMarshal程序包开发的踩坑经历 :)

    目录[阅读时间:约5分钟] 一.概述 1.Json的作用 2.Go官方 encoding/json 包 3. golang json的主要操作 二.Json Marshal:将数据编码成json字符串 ...

  2. 360浏览器 ajax取缓存,web开发遇到的坑之360浏览器缓存问题

    web开发遇到的坑之360浏览器缓存问题 再使用360浏览器,浏览我自己开发的一个配置的web管理后台时,发现,使用ctrl+F5都不能刷新表格的数据,还有,我添加字段时,明明是添加成功的,用sql再 ...

  3. iOS开发遇到的坑之五--解决工程已存在plist表,数据却不能存入的问题

    iOS开发遇到的坑之五--解决工程已存在plist表,数据却不能存入的问题 参考文章: (1)iOS开发遇到的坑之五--解决工程已存在plist表,数据却不能存入的问题 (2)https://www. ...

  4. 避免卷入办公室政治-开发就是这么坑!

    >>原创文章,欢迎转载.转载请注明:转载自IT人故事会,谢谢! >>原文链接地址:避免卷入办公室政治-开发就是这么坑 日天兄弟是我在2013年认识的,大高个,并且工作多年,人长 ...

  5. 美团·北极星开发对接避坑指北(Java)

    背景:公司做美团洗涤上门业务,本来好好的,后面美团要求接入美团·北极星订单预约接口,才能正常使用,没办法只能去接接口了,但是遇到了无数的坑,所以就有了这篇<美团·北极星开发对接避坑指北>, ...

  6. 微信小程序中开发的小坑

    微信小程序中开发的小坑 本文随时更新微信小程序开发过程中遇到的小坑.现已收集如下. 微信小程序编译后的大小不能超过1MB. 微信小程序不能建立两个(含)以上的WebStock连接.

  7. 2021-09-29 Unity WebGL平台开发遇到的坑

    内容简介:最近在用Unity做一个 WebGL 平台的项目,开发过程中遇到了各种各样的坑,这里简单记录一下,以免以后再踩.首先是Http请求的问题,我最开始想的是,直接用C#里的写法,编辑器里测试毫无 ...

  8. keil + STM32CubeMX 开发stm32L0 踩坑

    keil + STM32CubeMX 开发stm32L0 踩坑 我个人喜欢下载东西全部走官网 不喜欢去下别人给的乱七八糟的资源. 原因有二,一.找到头疼,版本说不定还旧.二.病毒,和各种奇奇怪怪的网盘 ...

  9. 游戏开发是个“坑”,而且是个“天坑”

    本文首发于CSDN公众号 作者 | 开发游戏的老王 责编 | 梦依丹 出品 | CSDN(ID:CSDNnews) 各位游戏开发者大家好,我是开发游戏的老王,一名游戏开发者同时也是一名高校游戏方向的主 ...

最新文章

  1. python中引入sql的优点_SQL Server 2017中的Python:增强的数据库内机器学习
  2. KNN-----Python程序学习(一)
  3. octave安装 缺java_Octave信号包安装
  4. java string fill_Java使用fill()数组填充的实现
  5. 漫步微积分五——速度和变化率
  6. 微信小程序 全局共享数据
  7. win764位和32位有什么区别_32位、64位它们是什么关系?它们又有什么区别?
  8. 欧空局2018机器学习系列课程发布:从概念到实践(视频+PPT)
  9. Silverlight 用户代码未处理 TypeLoadException
  10. java的反射机制的好处
  11. cocos2d-x基于windows平台交叉编辑android工程
  12. 微信浏览器ISO系统底部导航栏
  13. PHP文件运行步骤及数据库的连接
  14. 股票涨跌的心理学原理: 前景理论
  15. 打字时全部是繁体字,如何改为简体中文?
  16. 如何在微信朋友圈分享网页内容的时候能够有缩略图
  17. dobot示教程序ros
  18. 程序设计的三种基本结构
  19. python 爬取亚马逊评论_用Python爬取了三大相亲软件评论区,结果...
  20. 阿里云服务器实例规格选择,个人和企业分别选择哪种规格合适

热门文章

  1. Excel 表格图片压缩方法
  2. 树莓派声音输出设置_树莓派3 之 音响配置
  3. 树莓派3B+安装CentOS 7
  4. ubuntu查看 固态硬盘位置_在Ubuntu(Linux)中启用固态硬盘(固态硬盘)TRIM | MOS86...
  5. Android实现图片滚动控件,含页签功能,让你的应用像淘宝一样炫起来
  6. 《学会提问》——价值观假设和描述性假设
  7. HTML学习日记-第二篇
  8. Acwing - 算法基础课 - 笔记(数学知识 · 二)
  9. 计算机术语中的letters表示,letter是什么意思_letter在线翻译_英语_读音_用法_例句_海词词典...
  10. Java并发——Executor框架详解(Executor框架结构与框架成员)