关于项目中的NFC使用的流程

关于项目中的NFC使用的流程

第一次做NFC,主要是做一个记录。

初始化的时候是这样:

nfcUtils = new NfcUtils(this,getApplicationContext());
------------------------------------------------------
 /**
     * 构造函数,用于初始化nfc
     */
    public NfcUtils(Activity activity,Context context) {
        this.mContext = context;
        mNfcAdapter = NfcCheck(activity,mContext);
        NfcInit(activity,mContext);
    }
---------------------------------------------------
/**
     * 检查NFC是否打开
     */
    public static NfcAdapter NfcCheck(Activity activity,Context mContext) {
        NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
        if (mNfcAdapter == null) {
            return null;
        } else {
            if (!mNfcAdapter.isEnabled()) {
                Intent setNfc = new Intent(Settings.ACTION_NFC_SETTINGS);
                activity.startActivity(setNfc);
            }
        }
        return mNfcAdapter;
    }
----------------------------------------------------------
	/**
     * 初始化nfc设置
     */
    public static void NfcInit(Activity activity,Context mContext) {
    	Intent targetIntent = new Intent(activity, activity.getClass());
    	targetIntent .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        mPendingIntent = PendingIntent.getActivity(activity, 0,targetIntent, 0);
        IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        try {
            filter.addDataType("*/*");
        } catch (IntentFilter.MalformedMimeTypeException e) {
            e.printStackTrace();
        }
        mIntentFilter = new IntentFilter[]{filter, filter2};
        mTechList = null;
    }
-------------------------------------------------------
//开启前台调度系统
 NfcUtils.mNfcAdapter.enableForegroundDispatch(this, NfcUtils.mPendingIntent,
         NfcUtils.mIntentFilter, NfcUtils.mTechList);

然后我们在页面唤醒的任何时候将电子卡片靠近扫描的时候,会执行这样的方法:

	@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        intent1 = intent;
        //当该Activity接收到NFC标签时,运行该方法
        //调用工具方法,读取NFC数据
        try {
            String str = nfcUtils.readNFCFromTag(intent);
            et_code.setText(str);
            showToast(str);
            Log.d("122",str);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

刚开始的时候一脸懵逼,因为之前我做扫描的时候,差不多流程都是在页面注册一个广播接收者,然后每次扫描之后发出广播,然后把数据传回来,我看了好久也没看到类似这样广播服务的东西。

我只能在初始化的时候下点功夫,很明显,我们在开始的时候把Activity传到了NFCUtil中,然后添加了NfcAdapter.ACTION_NDEF_DISCOVEREDNfcAdapter.ACTION_TAG_DISCOVERED的过滤器,还构造了PendingIntent对象

pendingIntent的getActivity(Context, int, Intent, int)表示跳转到一个activity组件,真正的跳转是由参数intent决定的。

在我们这个例子中,真正的intent是跳转本页面,而且页面是以sigleTop的方式显示。

然后我们看resume中的开启前台调度系统方法,将我们的过滤器和这个intent都放进去了,这个mNfcAdapter.enableForegroundDispatch是系统的方法。

猜想
整个流程完了,不难看出是Application内部的服务每次收到NFC扫描操作的时候,就执行这个intent。在我这个项目中,就是以sigleton方式加载本页面,然后执行onNewIntent,读取intent中带的数据:intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);解析之后将数据回填。

验证

------------------------------Adapter源码  ---------------------------

public void enableForegroundDispatch(Activity activity, PendingIntent intent,
            IntentFilter[] filters, String[][] techLists) {
        synchronized (NfcAdapter.class) {
            if (!sHasNfcFeature) {
                throw new UnsupportedOperationException();
            }
        }
        if (activity == null || intent == null) {
            throw new NullPointerException();
        }
        // 只能在Resume这个方法中用这个方法
        if (!activity.isResumed()) {
            throw new IllegalStateException("Foreground dispatch can only be enabled " +
                    "when your activity is resumed");
        }
        try {
            TechListParcel parcel = null;
            if (techLists != null && techLists.length > 0) {
                parcel = new TechListParcel(techLists);
            }
	//暂停的时候自动调用disableForegroundDispatchInternal方法
	ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,mForegroundDispatchListener);
//终于找到了一个service
	sService.setForegroundDispatch(intent, filters, parcel);
        } catch (RemoteException e) {
        	// 发生异常之后恢复NFC服务
            attemptDeadServiceRecovery(e);
        }
    }

就上面所说,终于找到了一个Service,这个sService是INfcAdapter类,INfcAdapter是JNI实现的,这个setForegroundDispatch方法又把我们的intent和filter都丢进去了,JNI的实现我们看不见,但是这差不多已经很明显:我们类会被service重新跳转,然后进入onNewIntent方法,基本符合猜想。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值