手机访问NFC-SIM卡的SE

使用设备:MX3, 魅蓝note

调用:       Open Mobile API


问题描述:
1.nfc手机使用Open Mobile API访问到的是内置的nfc的SE?如何才能访问sim卡上的SE?

     使用MX3访问nfc-sim卡时,访问到的是内置的SE,没有显示可访问sim卡的SE。按照Open Mobile API的使用规范以及在网上的一些资料:http://blog.csdn.net/menghnhhuan/article/details/16940197,在创建,继承,实现接口之后,访问SE。在调用SEService.getReaders()时,不论手机是否插上了nfc-SIM卡,得到的readers数目始终是1。也就是说,手机只能访问到手机内部的SE,对nfc-sim卡中的SE始终“视而不见”。代码如下:(参考网上资料)

package com.example.test;

import org.simalliance.openmobileapi.Channel;
import org.simalliance.openmobileapi.Reader;
import org.simalliance.openmobileapi.SEService;
import org.simalliance.openmobileapi.Session;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.TextView;

public class MainActivity extends Activity implements SEService.CallBack {

	final String LOG_TAG = "HelloSmartcard";

	/**
	 * API entry point
	 */
	private SEService seService;
	NfcAdapter mNfc;
	TextView mTextView;

	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);
		mNfc = NfcAdapter.getDefaultAdapter(this);
		// do layout and UI stuff
		setContentView(R.layout.activity_main);
		
		mTextView = (TextView) this.findViewById(R.id.text);

		try {
			// create API entry point
		    mTextView.setText("creating new SEService\n");
			seService = new SEService(MainActivity.this, this);
		} catch (SecurityException e) {
		    mTextView.append("Binding not allowed, uses-permission SMARTCARD?");
		} catch (Exception e) {
			mTextView.append("Exception: " + e.getMessage());
		}
	}

	@Override
	protected void onDestroy() {
		if (seService != null && seService.isConnected()) {
			seService.shutdown();
		}
		super.onDestroy();
	}

	public void serviceConnected(SEService service) 
	{
		Session session = null;
        Channel basicChannel = null;
        mTextView.append("serviceConnected()\n");
        
        if(!service.isConnected())
        {
            Log.d(LOG_TAG, "seService is not Connected");
            mTextView.append("seService is not Connected");
            return;
        }
        
        try {
            mTextView.append("Getting available readers...\n");
            Reader[] readers = service.getReaders();
            
            //mTextView.append("The number of readers:" + readers.length + "\n");
            
            for(Reader reader:readers)
            {                       
                Log.i(LOG_TAG, "reader.name = " + reader.getName());
                mTextView.append("reader.name = " + reader.getName()+"\n");
            }

            mTextView.append("Getting Session ...\n");
            session = readers[0].openSession();         
            
            //is SE?
            if(readers[0].isSecureElementPresent()){
            	Log.v("SE", "HasSE");
            	mTextView.append("yes\n");
            }
            else {
            	Log.v("SE", "NoSE");
            	mTextView.append("No\n");
            }
            
            
            mTextView.append("open Session ...\n");
            //mTextView.append("ATR: "+ByteArrayToString(session.getATR())+"\n");
            
            byte[] aid = {(byte) 0xA0,0x00,0x00,0x00,0x03,0x00,0x00,0x00};
            basicChannel = session.openBasicChannel(aid);      
            mTextView.append("open Channel ...\n");
            
            byte[] CPLC = {(byte) 0x80,(byte) 0xca,(byte) 0x9f,0x7f,0x00};
            byte[] response1 = basicChannel.transmit(CPLC);                     
            mTextView.append("CPLC: "+ response1.toString() +"\n");               
            
            if(response1.length>=20)
            {
                mTextView.append(String.format("SerialID: %02x%02x%02x%02x\n", 
                        response1[15],response1[16],response1[17],response1[18]));    
            }
        } catch (Exception e) {
            mTextView.append("Error occured: "+e.getMessage()+"\n");
        }
        if(basicChannel!=null)
            basicChannel.close();
        if(session!=null)
            session.close();
	}

    private String ByteArrayToString(byte[] b) {
        StringBuffer s = new StringBuffer();
        for (int i = 0; i < b.length; i++) {
            s.append(Integer.toHexString(0x100 + (b[i] & 0xff)).substring(1));
        }
        return s.toString();
    }
}

运行结果如下:

手机访问NFC-SIM卡的SE_第1张图片


2.非nfc不能使用Open Mobile API访问?
    为了探是否可以成功使用Open Mobile API来访问nfc-sim卡,使用魅蓝note(不具有nfc功能),但是按照上述代码(去掉关于nfc的部分),连基本的SEService都无法连接。(理论上,访问sim卡的SE不需要nfc手机),具体运行结果显示图如下:

手机访问NFC-SIM卡的SE_第2张图片


3.猜想
    a. 是否需要某些操作把手机默认的SE设置到sim卡上,如果是,要怎么做?
    b. 是否只有nfc手机才支持Open Mobile API,非nfc手机系统把这个API精简了?


4.解决

    a. 使用的手机MX3没有内置SE,检查属性较慢,拔下卡后可能需要等待一段时间才能更新状态。

    b. 只要是android手机,就可以使用Open Mobile API来访问sim卡(前提是手机支持smartcard service),魅蓝note没有支持smartcard service。

    c. Smartcard service谷歌提供的代码,是通过检查sim卡是否存在,从而判断sim SE是否存在,所以,会存在普通卡也被识别成有SE这种不科学的情况。(据说谷歌这个是通过7816接口访问,不是通过SWP访问的,所以会有这个问题)


5.补充7816和SWP的一些知识

    a. SWP接口

手机访问NFC-SIM卡的SE_第3张图片

    b. 7816接口

手机访问NFC-SIM卡的SE_第4张图片

    c. SWP接口和7816在手机上结合

手机访问NFC-SIM卡的SE_第5张图片


刚刚开始接触这一方面的知识,很多不懂,有错误的地方望指出,共勉~



你可能感兴趣的:(android)