Android nfc读卡模式流程

最近一个项目需要将Android的nfc接口底层通过串口对接到外围一个单片机上,而nfc设备是接在单片机上的,这就需要对Android的nfc框架进行梳理,确定与单片机对接的接口通讯;上网查找发现资料不少,本次分析主要参考了以下大神的博客,基本上已经是非常清楚了!按照自己的理解对相关部分进行整理!

nfc的相关背景知识请参照此博客查阅即可:http://blog.csdn.net/xuwen0306/article/category/2926997


以下以开机,并且一个读卡流程,一一介绍整个顺序:

一、开机启动Nfc服务流程:

Android5.0\frameworks\base\services\core\Java\com\android\server\am\ActivityManagerService.java

 public void systemReady(final RunnablegoingCallback) {
          ....
          if (mFactoryTest !=FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                try {
                    List apps =AppGlobals.getPackageManager().
                       getPersistentApplications(STOCK_PM_FLAGS);
                    if (apps != null) {
                        int N = apps.size();
                        int i;
                        for (i=0; i<N; i++){
                            ApplicationInfoinfo
                                =(ApplicationInfo)apps.get(i);
                            if (info != null &&
                                   !info.packageName.equals("android")) {
                               addAppLocked(info, false, null /* ABI override */);
                            }
                        }
                    }
                } catch (RemoteException ex) {
                    // pm is in same process,this will never happen.
                }
         }
          ...
}

 

      继续分析addAppLocked()

final ProcessRecordaddAppLocked(ApplicationInfo info, boolean isolated,
            String abiOverride) {
          ...
        if (app.thread == null &&mPersistentStartingProcesses.indexOf(app) < 0) {
           mPersistentStartingProcesses.add(app);
            startProcessLocked(app, "addedapplication", app.processName, abiOverride,
                    null /* entryPoint */, null /*entryPointArgs */);
        }
          ...
}

 

      最终会call到NfcApplication.java中的NfcApplication()构造函数,其中的onCreate()会被调用到。   

@Override
    public void onCreate() {
        super.onCreate();
        boolean isMainProcess = false;
        // We start a service in a separateprocess to do
        // handover transfer. We don't want toinstantiate an NfcService
        // object in those cases, hence checkthe name of the process
        // to determine whether we're the mainNFC service, or the
        // handover process
        ActivityManager am =(ActivityManager)this.getSystemService(ACTIVITY_SERVICE);
        List processes =am.getRunningAppProcesses();
        Iterator i = processes.iterator();
        while (i.hasNext()) {
            //检查当前运行的App名字是否为"com.android.nfc",如果名字相同,则表示当前启动的程序是主程序
            RunningAppProcessInfo appInfo =(RunningAppProcessInfo)(i.next());
            if (appInfo.pid == Process.myPid()){
               isMainProcess =  (NFC_PROCESS.equals(appInfo.processName));
                break;
            }
        }
        if (UserHandle.myUserId() == 0&& isMainProcess) {</span>
            //启动NfcService
           mNfcService = new NfcService(this);
            HardwareRenderer.enableForegroundTrimming();
        }
    }




      当调用了new NfcService()之后,后面会依次创建各个Service。

 

     在进行后续分析前,简单的列举一下NFC的类图,方便后续的理解:

     上层APP主要透过调用android.nfc.tech及android.nfc的接口来实现期望的功能;而android.nfc.tech和android.nfc透过AIDL的方式调用到NfcService中的接口。Framework中NfcService透过JNI与底层NFC Driver进行沟通,实现发送命令和接收event功能。

 

 

 

 

        在进入NFCService.java前,需要对整个系统的架构有个初步的了解。

 

        DeviceHost.java定义了目前几乎NFC需要的全部interface和API。不同的厂家依据DeviceHost.java提供的interface,实现对应的内容,就可以和上层app进行沟通了。

 


二、开机启动流程2:

从流程1中就会new一个NfcService对象,具体的流程就略过了!请查看对应的博客即可;


三、接下来开始描述一整个读卡流程:

1、Android app打开nfc为开始

首先是app上,4.4以前通过以下调用打开:

var1 = NfcAdapter.getDefaultAdapter(this.t)
PendingIntent var3 = PendingIntent.getActivity(this.t, 0, (new Intent(this.t, this.t.getClass())).addFlags(536870912), 0);
IntentFilter[] var4 = new IntentFilter[0];
var1.enableForegroundDispatch((Activity)this.t, var3, var4, (String[][])null);

本文以Android 5.1版本描述读卡流程,5.1版本通过以下调用打开:

a、重写Callback

nfcCallBack = new NfcAdapter.ReaderCallback() {
@Override
public void onTagDiscovered(Tag tag) {
   // TODO Auto-generated method stub
  if(isNFC)
  {
   Message message = new Message();
                message.what = NFC_START;
                message.obj = tag;
                mHandler.sendMessage(message);
  }
}
        };
然后通过打开nfc

public boolean EnableSystemNFCMessage(ReaderCallback var1) {
    try {
        NfcAdapter var2;
        if((var2 = NfcAdapter.getDefaultAdapter(this.t)) != null && var2.isEnabled()) {
            Bundle var3;
            (var3 = new Bundle()).putInt("presence", 3000);
            var2.enableReaderMode((Activity)this.t, var1, d, var3);
            return true;
        } else {
            return false;
        }
    } catch (Exception var4) {
        var4.printStackTrace();
        return false;
    }
}

2、此时进入framework中,下面一个个记录调用顺序,本阶段为开启nfc扫描

frameworks/base/core/java/android/nfc/NfcAdapter.java:1276

        public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,Bundle extras)

frameworks/base/core/java/android/nfc/NfcActivityManager.java:206

        public void enableReaderMode(Activity activity, ReaderCallback callback, int flags,Bundle extras)

  public void setReaderMode(Binder token, int flags, Bundle extras)

 NfcAdapter.sService.setReaderMode(token, this, flags, extras);


PS:此处NfcAdapter.sService是通过NfcAdapter.java中的ServiceManager.getService("nfc")获取的,实际就是实例化packages/apps/Nfc/src/com/android/nfc/NfcService.java服务时,在构造函数中通过ServiceManager.addService(SERVICE_NAME, mNfcAdapter); 加入的,实际为NfcAdapterService实例


接上调用到:

packages/apps/Nfc/src/com/android/nfc/NfcService.java

935行:public void setReaderMode(IBinder binder, IAppCallback callback, int flags, Bundle extras)

 接着进入1441行:void applyRouting(boolean force) 开始读卡

        1472行:mDeviceHost.enableDiscovery(newParams, shouldRestart);

 

packages/apps/Nfc/nxp/src/com/android/nfc/dhimpl/NativeNfcManager.java(以nxp框架为例)

         167行:调用doEnableDiscovery函数,进入jni


packages/apps/Nfc/nxp/jni/com_android_nfc_NativeNfcManager.cpp

         static void com_android_nfc_NfcManager_enableDiscovery(JNIEnv *e, jobject o, jint modes, jboolean, jboolean reader_mode, jboolean enable_p2p, jboolean restart)

注册扫描nfc卡回调  ret = phLibNfc_RemoteDev_NtfRegister(&nat->registry_info, nfc_jni_Discovery_notification_callback, (void *)nat)


3、至此,设备开始进行nfc扫描;

接下来分析扫描到nfc卡之后,从调用回调函数开始:

packages/apps/Nfc/nxp/jni/com_android_nfc_NativeNfcManager.cpp

         905行: static void nfc_jni_Discovery_notification_callback(void *pContext, phLibNfc_RemoteDevList_t *psRemoteDevList, uint8_t uNofRemoteDev, NFCSTATUS status)


其中判断nfc类型,依照类型实例化cached_NfcTag(非接卡)或者cached_P2pDevice(Nfc设备),以下以非接卡继续说明:


1、实例化

ScopedLocalRef<jclass> tag_cls(e, e->GetObjectClass(nat->cached_NfcTag));

jmethodID ctor = e->GetMethodID(tag_cls.get(), "<init>", "()V");

tag.reset(e->NewObject(tag_cls.get(), ctor));   //以上三行实际就是获得cached_NfcTag的构造函数,然后将tag实例化为cached_NfcTag


PS:通过1629行:if(nfc_jni_cache_object(e,"com/android/nfc/dhimpl/NativeNfcTag",&(nat->cached_NfcTag)) == -1)  可知,cached_NfcTag实际就是packages/apps/Nfc/nxp/src/com/android/nfc/dhimpl/NativeNfcTag.java类  (implements TagEndpoint)


接下来将NativeNfcTag实例的各个数值初始化,包括支持的协议等,最后

e->CallVoidMethod(nat->manager, cached_NfcManager_notifyNdefMessageListeners, tag.get());通知上层进行处理


实际就是:

packages/apps/Nfc/nxp/src/com/android/nfc/dhimpl/NativeNfcManager.java

360行:private void notifyNdefMessageListeners(NativeNfcTag tag)

packages/apps/Nfc/src/com/android/nfc/NfcService.java

236行:public void onRemoteEndpointDiscovered(TagEndpoint tag)

sendMessage(NfcService.MSG_NDEF_TAG, tag);

本文件中的final class NfcServiceHandler extends Handler中对此消息进行处理;


播放声音等,然后调用

tag.startPresenceChecking(presenceCheckDelay, callback);

dispatchTagEndpoint(tag, readerParams);等发送消息到上层


最终在dispatchTagEndpoint中,调用回调将TagEndpoint,根据相应的信息,转换为tag类传到应用层;PS:最重要此处将TagService封装进了Tag类中



if (readerParams.callback != null) {
                        readerParams.callback.onTagDiscovered(tag); 


4、接下来又回到应用层,接收到nfc检测Tag:

应用层获取到Tag类之后,判断Tag类型后,可以通过具体的封装,获取对应的协议类进行处理,以下以NfcB举例:

    this.A = NfcB.get(var1);

    try {
        this.A.connect();
        if(this.A.isConnected()) {
            this.B = new m(this.A);
            return true;
        }
    } catch (IOException var7) {
      
    }


5、接下来应用可以自行调用NfcB等协议进行nfc卡的读写操作,以NfcB协议举例,西面是相关方法在framework中的位置:

frameworks/base/core/java/android/nfc/tech/NfcB.java

继承自frameworks/base/core/java/android/nfc/tech/BasicTagTechnology.java

内部依据具体的协议内容,最终通过传入的Tag类,获取TagService服务,通过TagService服务最终调用到NativeNfcTag中相应的connect,transceive等方法,与非接卡进行通讯;


自此,以流水账的形式将一个nfc的读卡流程描写完成!整体描述比较晦涩,后续再看看怎么样能够更好的表达记录nfc读卡流程



  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: ST25R NFC读卡器的开发流程主要包括以下几个步骤。 1. 硬件设计:首先,根据需求设计读卡器的硬件方案,包括电路板设计、天线设计等。考虑到读卡器的尺寸、功耗、性能等因素,选择合适的硬件元件。 2. 软件开发:在硬件设计完成后,需要进行软件开发。ST25R NFC读卡器可以使用STM32微控制器进行驱动。开发者需要使用相应的开发工具和编程语言,编写驱动程序,实现读卡器与NFC标签之间的通信协议等功能。 3. 集成测试:当硬件和软件开发完成后,需要进行集成测试。测试过程中,需要验证读卡器的功能是否正常,如能够正常读取NFC标签的信息,支持不同类型的NFC标签等。 4. 优化性能:在测试过程中,可能会发现一些改进的地方,比如增加读写速度、提高读取距离等。开发者需要根据测试结果进行性能优化,修改硬件和软件参数,以满足项目的要求。 5. 量产生产:当读卡器的功能和性能都满足要求后,可以进行量产生产。这包括制造读卡器的PCB板、组装硬件元件、安装软件等工作。 6. 上市销售:最后一步是将读卡器推向市场销售。开发者需要确定合适的市场渠道,制定推广策略,并与销售渠道合作,将读卡器推向消费者。 总之,ST25R NFC读卡器的开发流程包括硬件设计、软件开发、集成测试、性能优化、量产生产和市场推广等方面。不同项目可能会有所差异,但以上步骤是较为通用的流程。 ### 回答2: ST25R NFC读卡器的开发流程通常包括以下几个步骤: 1. 硬件设计:首先需要设计读卡器的硬件电路,包括选择适当的ST25R系列芯片、天线设计、电源电路、通信接口等。硬件设计需要考虑功耗、通信性能、成本和尺寸等因素。 2. 软件开发:在硬件设计完成之后,需要进行软件开发。首先是为ST25R芯片编写驱动程序,使其能够正确运行并实现读卡器的基本功能。然后,根据具体需求,开发应用软件来实现不同的功能,如读取NFC标签数据、与其他设备进行通信等。 3. 软硬件集成:将软件与硬件进行集成,确保软件可以正确地与硬件交互。这一步需要进行严格的测试和调试,以确保读卡器的稳定性和可靠性。 4. NFC标准和认证:在开发过程中,需要遵循NFC标准和认证要求,以确保读卡器的兼容性和互操作性。此外,如果需要将读卡器用于特定行业或场景,还需要进行相关的认证和合规性测试。 5. 集成测试和优化:在完成软硬件集成后,需要进行集成测试,以验证读卡器的功能和性能。根据测试结果,进行必要的优化调整,以达到预期的性能指标。 6. 批量生产和上市:当读卡器开发完成,经过验证和优化后,可以进行批量生产,并进行市场推广和销售。此阶段还需要与供应链合作,确保产品的稳定供应和售后服务等。 总之,ST25R NFC读卡器的开发流程包括硬件设计、软件开发、软硬件集成、NFC标准和认证、集成测试和优化以及批量生产和上市等多个环节,其中每个环节都需要经过严格的测试和调试,以确保读卡器的功能和性能达到预期。 ### 回答3: ST25R NFC读卡器的开发流程可以分为以下几个步骤。 首先,确定需求和功能。确定开发的目标和所需要的功能,例如读写NFC标签、处理通信协议等。 其次,选取适当的硬件平台。ST25R系列提供了不同型号的NFC读卡器模块,选择适合项目需求的模块,比如ST25R3911或ST25R3916。 然后,进行硬件布局设计。根据选定的硬件平台,设计电路和布局,并确保它们符合NFC的相关规范和指导。 接下来,进行软件开发。使用ST25 SDK提供的开发工具和API,编写软件代码来控制NFC读卡器模块。这些代码可能包括初始化读卡器、读写NFC标签、处理通信协议等功能。 在软件开发期间,可以通过调试工具来测试和验证开发的功能。ST25R系列提供了相应的调试工具和示例代码,可以方便地进行调试和验证。 最后,进行系统集成和测试。将开发的硬件和软件进行集成,并进行全面的测试,确保读卡器的功能和性能符合设计要求。 总结起来,ST25R NFC读卡器的开发流程包括确定需求和功能、选取硬件平台、进行硬件布局设计、软件开发、调试和验证以及系统集成和测试等环节。通过按照这个流程进行开发,可以确保最终的产品能够满足需求并达到预期的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值