androidstudio基于bmob平台实现NFC读合法卡/非法卡、写卡功能

androidstudio基于bmob平台实现NFC读合法卡/非法卡、写卡功能

一、Java文件

package com.example.smartcommunityv2;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.nfc.tech.NfcA;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.widget.EditText;
import android.widget.Toast;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;

import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.QueryListener;
import cn.bmob.v3.listener.SaveListener;

@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
public class realnfcmain extends AppCompatActivity {
    private EditText nfcdata ;

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_realnfcmain);
        Bmob.initialize(this, "992f7d755c2df83e885dade0f4d892c6");
//        NfcUtils nfcUtils = new NfcUtils(this);
    }

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    @Override
    protected void onResume() {
        super.onResume();
        //设定intentfilter和tech-list。如果两个都为null就代表优先接收任何形式的TAG action。也就是说系统会主动发TAG intent。
        if (mNfcAdapter != null) {
            mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, mIntentFilter, mTechList);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    @Override
    protected void onPause() {
        super.onPause();
        if (mNfcAdapter != null) {
            mNfcAdapter.disableForegroundDispatch(this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mNfcAdapter = null;
    }

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        readWrite(intent);
    }

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    public void readWrite(Intent intent) {
        nfcdata =  findViewById(R.id.nfcdata);
        String data2 = nfcdata.getText().toString();
        try {

            // 检测卡的id
            String id = readNFCId(intent);
            // NfcUtils中获取卡中数据的方法
            String result = readNFCFromTag(intent);

            BmobQuery<BmobUser> bmobuser = new BmobQuery<>();
            bmobuser.getObject(result, new QueryListener<BmobUser>() {
                @Override
                public void done(BmobUser bmobuser, BmobException e) {
                    if (e == null) {
                        Toast.makeText(realnfcmain.this,"门禁已开",Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(realnfcmain.this,"警告,请使用合法卡",Toast.LENGTH_SHORT).show();
                    }
                }
            });

            if(nfcdata.getText().toString().length() != 0){
                // 往卡中写数据
                writeNFCToTag(this,data2,intent);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }  catch (IOException e) {
            e.printStackTrace();
        } catch (FormatException e) {
            e.printStackTrace();
        }
    }

    public static NfcAdapter mNfcAdapter;
    public static IntentFilter[] mIntentFilter = null;
    public static PendingIntent mPendingIntent = null;
    public static String[][] mTechList = null;

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    public void NfcUtils(Activity activity) {
        mNfcAdapter = NfcCheck(activity);
        NfcInit(activity);
    }

    public static void readNFCFromTag() {
    }

    /**
     * 检查NFC是否打开
     */
    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    public NfcAdapter NfcCheck(Activity activity) {
        NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
        if (mNfcAdapter == null) {
            Toast.makeText(this,"设备不支持NFC功能!",Toast.LENGTH_SHORT).show();
            return null;
        } else {
            if (!mNfcAdapter.isEnabled()) {
                IsToSet(activity);
            } else {
                Toast.makeText(this,"NFC功能已打开!",Toast.LENGTH_SHORT).show();

            }
        }
        return mNfcAdapter;
    }

    /**
     * 初始化nfc设置
     */
    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    public static void NfcInit(Activity activity) {
        Intent intent = new Intent(activity, activity.getClass());
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        mPendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);
        //做一个IntentFilter过滤你想要的action 这里过滤的是ndef
        IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            filter.addDataType("*/*");
        } catch (IntentFilter.MalformedMimeTypeException e) {
            e.printStackTrace();
        }
        mTechList = new String[][]{{MifareClassic.class.getName()},
                {NfcA.class.getName()}};
        //生成intentFilter
        mIntentFilter = new IntentFilter[]{filter};
    }

    /**
     * 读取NFC的数据
     */
    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
    public  String readNFCFromTag(Intent intent) throws UnsupportedEncodingException {
        Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawArray != null) {
            NdefMessage mNdefMsg = (NdefMessage) rawArray[0];
            NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];
            if (mNdefRecord != null) {
                return parseTextRecord(mNdefRecord);
            }
        }
        return "";
    }

    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    public void writeNFCToTag(Context context, String data, Intent intent) throws IOException, FormatException {
        NdefRecord ndefRecord = null;
        ndefRecord=createTextRecord(data);
        NdefRecord[] records = {ndefRecord};

        NdefMessage ndefMessage = new NdefMessage(records);

        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        Ndef ndef = Ndef.get(tag);
        if(ndef==null){
            NdefFormatable format = NdefFormatable.get(tag);
            format.connect();
            format.format(ndefMessage);
            if(format.isConnected()){
                format.close();
            }
            return;
        }

        ndef.connect();
        if(!ndef.isWritable()){
            Toast.makeText(this,"当前设备不支持写入",Toast.LENGTH_SHORT).show();
            return;
        }
        //判断大小

        ndef.writeNdefMessage(ndefMessage);
        if(ndef.isConnected()){
            ndef.close();
        }
        Toast.makeText(this,"读写完毕",Toast.LENGTH_SHORT).show();

    }

    /**
     * 读取nfcID
     */
    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
    public static String readNFCId(Intent intent) throws UnsupportedEncodingException {
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        String id = ByteArrayToHexString(tag.getId());
        return id;
    }

    private static String ByteArrayToHexString(byte[] inarray) {
        int i, j, in;
        String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
        String out = "";
        for (j = 0; j < inarray.length; ++j) {
            in = (int) inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
        }
        return out;
    }

    private static void IsToSet(final Activity activity) {
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setMessage("是否跳转到设置页面打开NFC功能");
        builder.setTitle("提示");
        builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                goToSet(activity);
                dialog.dismiss();
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.create().show();
    }

    private static void goToSet(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BASE) {
            // 进入设置系统应用权限界面
            Intent intent = new Intent(Settings.ACTION_SETTINGS);
            activity.startActivity(intent);
            return;
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {// 运行系统在5.x环境使用
            // 进入设置系统应用权限界面
            Intent intent = new Intent(Settings.ACTION_SETTINGS);
            activity.startActivity(intent);
            return;
        }
    }

    /**
     * 创建NDEF文本数据
     * @param text
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
    public static NdefRecord createTextRecord(String text) {
        byte[] langBytes = Locale.CHINA.getLanguage().getBytes(Charset.forName("US-ASCII"));
        Charset utfEncoding = Charset.forName("UTF-8");
        //将文本转换为UTF-8格式
        byte[] textBytes = text.getBytes(utfEncoding);
        //设置状态字节编码最高位数为0
        int utfBit = 0;
        //定义状态字节
        char status = (char) (utfBit + langBytes.length);
        byte[] data = new byte[1 + langBytes.length + textBytes.length];
        //设置第一个状态字节,先将状态码转换成字节
        data[0] = (byte) status;
        //设置语言编码,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1到langBytes.length的位置
        System.arraycopy(langBytes, 0, data, 1, langBytes.length);
        //设置文本字节,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1 + langBytes.length
        //到textBytes.length的位置
        System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
        //通过字节传入NdefRecord对象
        //NdefRecord.RTD_TEXT:传入类型 读写
        NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                NdefRecord.RTD_TEXT, new byte[0], data);
        return ndefRecord;
    }

    /**
     * 解析NDEF文本数据,从第三个字节开始,后面的文本数据
     * @param ndefRecord
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
    public  String parseTextRecord(NdefRecord ndefRecord) {
        /**
         * 判断数据是否为NDEF格式
         */
        //判断TNF
        if (ndefRecord.getTnf() != NdefRecord.TNF_WELL_KNOWN) {
            return null;
        }
        //判断可变的长度的类型
        if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
            return null;
        }
        try {
            //获得字节数组,然后进行分析
            byte[] payload = ndefRecord.getPayload();
            //下面开始NDEF文本数据第一个字节,状态字节
            //判断文本是基于UTF-8还是UTF-16的,取第一个字节"位与"上16进制的80,16进制的80也就是最高位是1,
            //其他位都是0,所以进行"位与"运算后就会保留最高位


            String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" : "UTF-16";
//            LogUtils.e("parseTextRecord() textEncoding="+textEncoding);
            //3f最高两位是0,第六位是1,所以进行"位与"运算后获得第六位
            int languageCodeLength = payload[0] & 0x3f;
            //下面开始NDEF文本数据第二个字节,语言编码
            //获得语言编码
            String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
//            LogUtils.e("parseTextRecord() languageCode="+languageCode);


            //下面开始NDEF文本数据后面的字节,解析出文本
            String textRecord = new String(payload, languageCodeLength + 1,
                    payload.length - languageCodeLength - 1, textEncoding);
            Toast.makeText(this,textRecord,Toast.LENGTH_LONG).show();
            return textRecord;
        } catch (Exception e) {
            throw new IllegalArgumentException();
        }
    }
}

二、XML文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".realnfcmain"
    android:background="@color/black">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/nfcdata"
        android:layout_marginTop="300dp"
        android:hint="输入文本可修改NFC卡内容"
        android:textColor="@color/white"
        android:textColorHint="#bcbcbc">
    </EditText>
</LinearLayout>

三、配置

<uses-permission android:name="android.permission.NFC" />

<activity
            android:name=".realnfcmain"
            android:launchMode="singleInstance">
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>

四、演示图片

在这里插入图片描述读取合法卡
在这里插入图片描述开启门🈲

在这里插入图片描述读取非法卡
在这里插入图片描述无法开启门禁
在这里插入图片描述写卡
在这里插入图片描述再次读卡

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人生只为一个成果

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值