当前位置:   article > 正文

uniapp调用原生安卓读写NFC解决方案_uniapp nfc

uniapp nfc

项目场景:

例如:项目场景:现场每个环节需要用到NFC芯片来读写数据,网上找了很多都没有符合要求的,只能根据芯片的类型来找对应的解决方案,然后整合到一起,下面我会着重讲一下每一步怎么操作。


解决方案

简单的描述一下这个过程,可能不准确,大家理解即可。
请添加图片描述

NFC芯片的类型: ISO15693
此类芯片我们按要求写入到指定的块区域,读取也是一样。具体请查询有关ISO15693协议文档,这里不做赘述。

1、第一步先去uniapp官网下载demo,然后根据以下代码自行修改,关于什么appkey配置什么的自行研究。地址:https://nativesupport.dcloud.net.cn/AppDocs/

使用Android Studio打开下载好的uniapp文件,选择以下的模块打开。
在这里插入图片描述
2、

package io.dcloud.uniplugin;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;

import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;


public class TestModule extends UniModule {

	//定义一个标签,用于uniapp调API之前,指定哪个标签
    String TAG = "TestModule";
    public static int REQUEST_CODE = 1000;

	//这个是重点,你需要返回到当前uniapp请求的JS的回调里面,声明全局变量,下面第三个方法会用到
    private UniJSCallback mCallback;

    //这个就是安卓原生里面的写入接口
    @UniJSMethod(uiThread = true)
    public void writeFunc(JSONObject options, UniJSCallback callback) {
    	//上面传入的options,就是uniapp JS方法传入的参数
        this.mCallback = callback;
        Log.e(TAG, "writeFunc--"+options);
        if(callback != null) {
            if(mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) {
            	//跳转到写标签的Activity里面,这样才能操作NFC读写芯片
                Intent intent = new Intent(mUniSDKInstance.getContext(), NativePage2Activity.class);
                Bundle bundle = new Bundle();
                //这里是需要向跳转的Activity里面传你需要处理的数据
                bundle.putString("参数1","xxx");
                intent.putExtras(bundle);
                ((Activity)mUniSDKInstance.getContext()).startActivityForResult(intent, REQUEST_CODE);
            }
        }
    }


    //这个就是安卓原生里面的读取接口
    @UniJSMethod (uiThread = false)
    public void readFunc(JSONObject options, UniJSCallback callback){
    //上面传入的options,就是uniapp JS方法传入的参数
        this.mCallback = callback;
        Log.e(TAG, "readFunc--"+options);
        if(callback != null) {
            if(mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) {
            	//跳转到读标签的Activity里面,这样才能操作NFC读写芯片
                Intent intent = new Intent(mUniSDKInstance.getContext(), NativePageActivity.class);
                Bundle bundle = new Bundle();
                //这里是需要向跳转的Activity里面传你需要处理的数据
                bundle.putString("参数1","xxx");
                intent.putExtras(bundle);
                ((Activity)mUniSDKInstance.getContext()).startActivityForResult(intent, REQUEST_CODE);
            }
        }
    }

	//这个方法就是接收上面读写API调转Activity后读写成功并返回的方法
	//接收到返回数据后,将数据通过mCallback,返回给uniapp
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode == REQUEST_CODE && data.hasExtra("respond")) {
            String string = data.getStringExtra("respond");
            Log.e("TestModule", "原生页面返回----"+string);
            mCallback.invoke(string);
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    }

	//这是自带的,可忽略
    @UniJSMethod (uiThread = true)
    public void gotoNativePage(){
        if(mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) {
            Intent intent = new Intent(mUniSDKInstance.getContext(), NativePageActivity.class);
            ((Activity)mUniSDKInstance.getContext()).startActivityForResult(intent, REQUEST_CODE);
        }
    }


}



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

3、写入Activity

package io.dcloud.uniplugin;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.NfcV;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.fastjson.JSONObject;

import java.io.IOException;


public class NativePage2Activity extends Activity {
    String TAG = "TestModule";
    public NfcV nfcV;
    public NfcVUtil util;
    private NfcAdapter mNfcAdapter;
    private PendingIntent mPendingIntent;
    private TextView mContent;

 
    String data = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        Bundle bundle = this.getIntent().getExtras();
        mContent = findViewById(R.id.content);
        mContent.setText(bundle.getString("参数1"));
    }

    @Override
    protected void onStart() {
        super.onStart();
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        // 用于感应到NFC时启动该Activity
        // 这里建议将处理NFC的子类的launchMode设置成singleTop模式,这样感应到标签时就会回调onNewIntent,而不会重复打开页面
        mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0);
    }

    /**
     * 获得焦点,按钮可以点击
     */
    @Override
    public void onResume() {
        super.onResume();
        // 设置当该页面处于前台时,NFC标签会直接交给该页面处理
        if (mNfcAdapter != null) {
            mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
        }
    }

    /**
     * 暂停Activity,界面获取焦点,按钮可以点击
     */
    @Override
    public void onPause() {
        super.onPause();
        // 当页面不可见时,NFC标签不交给当前页面处理
        if (mNfcAdapter != null) {
            mNfcAdapter.disableForegroundDispatch(this);
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (detectedTag != null) {
            byte[] aa = detectedTag.getId();
            String str = ByteArrayToHexString(aa);
            String UID = flipHexStr(str);
//            Toast.makeText(this, "RFID已经连接",
//                    Toast.LENGTH_LONG).show();
            try {
                nfcV = NfcV.get(detectedTag);
                if (nfcV != null) {
                    nfcV.connect();//建立连接
                    util = new NfcVUtil(nfcV);//创建工具类,操作连接
                }
                data = "";
                write();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void write() {
        if (!isEnable()) {
            return;
        }
        try {
            String info = mContent.getText().toString();
            info.replaceAll("[^a-zA-Z0-9]", "");
            //为a-f的8长度的字符串,转换成byte数组长度为4
            //第一个参数为块索引,第二个参数为4长度的byte数组。如数据不够,需要补位
            if (info.length() == 0) {
                Toast.makeText(this, "字符不能为空", Toast.LENGTH_LONG).show();
                return;
            }
            if (info.length() > 50) {
                Toast.makeText(this, "超出限制50字符", Toast.LENGTH_LONG).show();
                return;
            }
            //这里代表,在每次写入之前都要清空,这里暂定50个字符,大家自行调整
            for (int i = 2; i <= 14; i++) {
                if (i != 14) {
                    util.writeBlock(i, util.hexStringToBytes("00000000"));
                } else {
                    util.writeBlock(i, util.hexStringToBytes("0000"));
                }
            }
            boolean flag = false;
            int len = info.length() / 4;
            if (info.length() > 4 * len) {
                len = len + 1;
                flag = true;
            }
            boolean b = false;
            String substring = "";
            for (int i = 0; i < len; i++) {
                if (i == len - 1 && flag) {
                    substring = info.substring(i * 4);
                } else {
                    substring = info.substring(i * 4, (i + 1) * 4);
                }
                b = util.writeBlock((2 + i), util.hexStringToBytes(stringToHex(substring)));
            }
            if (b) {
                Toast.makeText(this, "写入成功", Toast.LENGTH_LONG).show();
            } else {
                Toast.makeText(this, "写入失败", Toast.LENGTH_LONG).show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String stringToHex(String input) {
        StringBuilder hexString = new StringBuilder();
        for (int i = 0; i < input.length(); i++) {
            char c = input.charAt(i);
            hexString.append(Integer.toHexString((int) c));
        }
        return hexString.toString();
    }

  public static String flipHexStr(String s) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i <= s.length() - 2; i = i + 2) {
            result.append(new StringBuilder(s.substring(i, i + 2)).reverse());
        }
        return result.reverse().toString();
    }

    public 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 = inarray.length - 1; j >= 0; j--) {
            in = (int) inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
        }
        return out;
    }
    
    public boolean isEnable() {
        if (util == null) {
            //请先连接RFID卡
            return false;
        }
        if (nfcV == null) {
            //请先连接RFID卡
            return false;
        }
        if (!nfcV.isConnected()) {
            //接连中断,请重新连接
            return false;
        }
        return true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193

这是写入弹出的页面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >


    <ImageView
        android:id="@+id/imageView"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/icon_scan"
        />
    <TextView
        android:id="@+id/content"
        android:textSize="16dp"
        android:gravity="center_horizontal"
        android:textStyle="bold"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <TextView
        android:layout_marginTop="5dp"
        android:id="@+id/content2"
        android:textSize="15dp"
        android:hint="靠近标签自动写入数据"
        android:gravity="center_horizontal"
        android:textColorHint="#95A1AA"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="30dp"
        />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

页面大概是这样的,图片自行更换,这里就不贴出。
在这里插入图片描述
4、读取Activity

package io.dcloud.uniplugin;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.NfcV;
import android.os.Bundle;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import com.alibaba.fastjson.JSONObject;

import java.io.IOException;

public class NativePageActivity extends Activity {
    String TAG = "TestModule";
    public NfcV nfcV;
    public NfcVUtil util;
    private NfcAdapter mNfcAdapter;
    private PendingIntent mPendingIntent;
    String data = "";
    String xxx= "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Bundle bundle = this.getIntent().getExtras();
        xxx= bundle.getString("参数1");
    }

    @Override
    protected void onStart() {
        super.onStart();
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        // 用于感应到NFC时启动该Activity
        // 这里建议将处理NFC的子类的launchMode设置成singleTop模式,这样感应到标签时就会回调onNewIntent,而不会重复打开页面
        mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0);
    }

    /**
     * 获得焦点,按钮可以点击
     */
    @Override
    public void onResume() {
        super.onResume();
        // 设置当该页面处于前台时,NFC标签会直接交给该页面处理
        if (mNfcAdapter != null) {
            mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
        }
    }

    /**
     * 暂停Activity,界面获取焦点,按钮可以点击
     */
    @Override
    public void onPause() {
        super.onPause();
        // 当页面不可见时,NFC标签不交给当前页面处理
        if (mNfcAdapter != null) {
            mNfcAdapter.disableForegroundDispatch(this);
        }
    }

    @Override
    public void onNewIntent(Intent intent) {
        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (detectedTag != null) {
            byte[] aa = detectedTag.getId();
            String str = ByteArrayToHexString(aa);
            String UID = flipHexStr(str);
//            Toast.makeText(this, "RFID已经连接",
//                    Toast.LENGTH_SHORT).show();
            try {
                nfcV = NfcV.get(detectedTag);
                if (nfcV != null) {
                    nfcV.connect();//建立连接
                    util = new NfcVUtil(nfcV);//创建工具类,操作连接
                }
                data = "";
                read();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public void read() {
        if (!isEnable()) {
            return;
        }
        这里从第2块区域读50个字符,0,1块号主要是芯片定义好的身份信息
        int blockText2 = 2;
        int blockNum2 = 13;
        try {
            int i;
            for (i = blockText2; i <= blockNum2 + blockText2 - 1; ++i) {
                String readOneBlockStr = util.readOneBlock(i);//读取block在1位置的内容
                data = data + readOneBlockStr;
            }
            data = data.replaceAll("[^a-zA-Z0-9]", "");
            //这里将读取的数据,返回到接口类中
            Intent intent = new Intent();
            intent.putExtra("respond", data);
            setResult(TestModule.REQUEST_CODE, intent);
            finish();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String flipHexStr(String s) {
        StringBuilder result = new StringBuilder();
        for (int i = 0; i <= s.length() - 2; i = i + 2) {
            result.append(new StringBuilder(s.substring(i, i + 2)).reverse());
        }
        return result.reverse().toString();
    }

    public 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 = inarray.length - 1; j >= 0; j--) {
            in = (int) inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
        }
        return out;
    }

    public boolean isEnable() {
        if (util == null) {
            //请先连接RFID卡
            return false;
        }
        if (nfcV == null) {
            //请先连接RFID卡
            return false;
        }
        if (!nfcV.isConnected()) {
            //接连中断,请重新连接
            return false;
        }
        return true;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <ImageView
        android:id="@+id/imageView"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/icon_scan"
        />

    <TextView
        android:layout_marginTop="20dp"
        android:id="@+id/content"
        android:textSize="15dp"
        android:hint="靠近标签自动读取数据"
        android:gravity="center_horizontal"
        android:textColorHint="#95A1AA"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="30dp"
        />
</LinearLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

在这里插入图片描述
5、NFC工具类,自行导入


package io.dcloud.uniplugin;
import android.nfc.tech.NfcV;

import java.io.IOException;

public class NfcVUtil {

    private NfcV mNfcV;
    /**UID数组行式*/
    private byte[] ID;
    private String UID;
    private String DSFID;
    private String AFI;
    /**block的个数*/
    private int blockNumber;
    /**一个block长度*/
    private int oneBlockSize;
    /**信息*/
    private byte[] infoRmation;

    /**
     * 初始化
     * @param mNfcV NfcV对象
     * @throws IOException
     */
    public NfcVUtil(NfcV mNfcV) throws IOException{
        this.mNfcV = mNfcV;
        ID = this.mNfcV.getTag().getId();
        byte[] uid = new byte[ID.length];
        int j = 0;
        for(int i = ID.length - 1; i >=0; i-- ){
            uid[j] = ID[i];
            j++;
        }
        this.UID = printHexString(uid);
        getInfoRmation();//获取标签的信息
    }
    public String getUID() {
        return UID;
    }


    /**
     * 取得标签信息
     */
    private byte[] getInfoRmation() throws IOException{
        byte[] cmd = new byte[10];
        cmd[0] = (byte) 0x22; // flag
        cmd[1] = (byte) 0x2B; // command
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        infoRmation = mNfcV.transceive(cmd);
        blockNumber = infoRmation[12];//可使用的数据块数量,一般为27
        oneBlockSize = infoRmation[13];//每个块byte数组的长度,一般为4
        AFI = printHexString(new byte[]{infoRmation[11]});//AFI值在某些领域会需要使用
        DSFID = printHexString(new byte[]{infoRmation[10]});//DSFID值
        return infoRmation;
    }

    /**
     * 写入AFI数据
     * @param b
     * @return
     * @throws IOException
     */
    public boolean setAFIState(byte b) throws IOException {
        byte[] cmd = new byte[11];
        cmd[0] = (byte) 0x22; // flag
        cmd[1] = (byte) 0x27; // command
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        cmd[10] = b;
        byte[] res = mNfcV.transceive(cmd);
        if(res[0] == 0x00){
            byte[] cmdNew = new byte[10];
            cmdNew[0] = (byte) 0x22; // flag
            cmdNew[1] = (byte) 0x2B; // command
            System.arraycopy(ID, 0, cmdNew, 2, ID.length); // UID
            AFI = printHexString(new byte[]{infoRmation[11]});
            DSFID = printHexString(new byte[]{infoRmation[10]});

            return true;

            //千万不要锁定,不可逆
//            byte[] cmd2 = new byte[10];
//            cmd2[0] = (byte) 0x22; // flag
//            cmd2[1] = (byte) 0x28; // command
//            System.arraycopy(ID, 0, cmd2, 2, ID.length); // UID
//            byte[] res2 = mNfcV.transceive(cmd2);
//            if(res2[0] == 0x00){
//               return true;
//            }
        }
        return false;
    }

    /**
     * 写入DSFID数据
     * @param b
     * @return
     * @throws IOException
     */
    public boolean setDSFIDState(byte b) throws IOException {
        byte[] cmd = new byte[11];
        cmd[0] = (byte) 0x22; // flag
        cmd[1] = (byte) 0x29; // command
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        cmd[10] = b;
        byte[] res = mNfcV.transceive(cmd);
        if(res[0] == 0x00){
            byte[] cmdNew = new byte[10];
            cmdNew[0] = (byte) 0x22; // flag
            cmdNew[1] = (byte) 0x2B; // command
            System.arraycopy(ID, 0, cmdNew, 2, ID.length); // UID
            AFI = printHexString(new byte[]{infoRmation[11]});
            DSFID = printHexString(new byte[]{infoRmation[10]});
            return true;

            //千万不要锁定,不可逆
//            byte[] cmd2 = new byte[10];
//            cmd2[0] = (byte) 0x22; // flag
//            cmd2[1] = (byte) 0x2A; // command
//            System.arraycopy(ID, 0, cmd2, 2, ID.length); // UID
//            byte[] res2 = mNfcV.transceive(cmd2);
//            if(res2[0] == 0x00){
//                return true;
//            }
        }
        return false;
    }
    public String getDSFID() {
        return DSFID;
    }

    public String getAFI() {
        String temp = String.valueOf(mNfcV.getDsfId());
//        return AFI;
        return temp + AFI;
    }

    /**
     * 读取一个位置在position的block
     * @param position 要读取的block位置
     * @return 返回内容字符串
     * @throws IOException
     */
    public String readOneBlock(int position) throws IOException{
        byte cmd[] = new byte[12];
        cmd[0] = (byte) 0x22;
        cmd[1] = (byte) 0x23;//0x20
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        cmd[10] = (byte) position;
        cmd[11] = (byte) 0;
        byte res[] = mNfcV.transceive(cmd);
        if(res[0] == 0x00){
            byte block[] = new byte[res.length - 1];
            System.arraycopy(res, 1, block, 0, res.length - 1);
            return AToString(block);
        }
        return null;
    }


    public  String AToString(byte block[]){
        StringBuffer s = new StringBuffer();
        for (int i = 0; i < block.length; i++) {
            s.append(Character.toString((char)block[i]));
        }
        return s.toString();
    }

    /**
     * String转Hex格式Byte[]
     * @param hexString
     * @return
     */
    public byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));

        }
        return d;
    }
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }
    /**
     * 将byte[]转换成16进制字符串
     * @param data 要转换成字符串的字节数组
     * @return 16进制字符串
     */
    private String printHexString(byte[] data) {
        StringBuffer s = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            String hex = Integer.toHexString(data[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            s.append(hex);
        }
        return s.toString();
    }

    //结果大写
    private 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 = inarray.length - 1; j >= 0 ; j--) {
            in = (int) inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
        }
        return out;
    }


    /**
     * 将数据写入到block,
     * @param position 要写内容的block位置
     * @param data 要写的内容,必须长度为blockOneSize
     * @return false为写入失败,true为写入成功
     * @throws IOException
     */
    public boolean writeBlock(int position, byte[] data) throws IOException{
        byte cmd[] = new byte[15];
        cmd[0] = (byte) 0x22;
        cmd[1] = (byte) 0x21;
        System.arraycopy(ID, 0, cmd, 2, ID.length); // UID
        //block
        cmd[10] = (byte) position;
        //value
        System.arraycopy(data, 0, cmd, 11, data.length);
        byte[]rsp = mNfcV.transceive(cmd);
        if(rsp[0] == 0x00)
            return true;
        return false;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250

6、AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="io.dcloud.uniplugin">

    <!-- 添加NFC权限 -->
    <uses-permission android:name="android.permission.NFC" />
    <!-- 要求当前设备必须要有NFC芯片 -->
    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />
    <application>
        <activity
            android:name="io.dcloud.uniplugin.NativePageActivity"
            android:exported="true"
            android:label="@string/app_name"
            android:launchMode="singleTop"
            android:theme="@android:style/Theme.Holo.Light.Dialog.NoActionBar.MinWidth">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>
        <activity
            android:name="io.dcloud.uniplugin.NativePage2Activity"
            android:exported="true"
            android:label="@string/app_name2"
            android:launchMode="singleTop"
            android:theme="@android:style/Theme.Holo.Light.Dialog.NoActionBar.MinWidth">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
            </intent-filter>
        </activity>
        <meta-data
            android:name="dcloud_appkey"
            android:value="这里自己去uniapp官网申请" />
    </application>
</manifest>

strings.xml配置
<resources>
    <string name="app_name">读电子标签</string>
    <string name="app_name2">写电子标签</string>
</resources>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

7、build.gradle配置,根据个人SDK版本来配置

apply plugin: 'com.android.library'
android {
    namespace 'io.dcloud.uniplugin'
    compileSdkVersion 29
    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

}

repositories {
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    compileOnly fileTree(dir: 'libs', include: ['*.jar'])
    compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar'])
    compileOnly 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
    compileOnly 'androidx.recyclerview:recyclerview:1.0.0'
    compileOnly 'androidx.core:core:1.1.0'
    compileOnly 'androidx.fragment:fragment:1.1.0'
    compileOnly 'androidx.appcompat:appcompat:1.1.0'
    compileOnly 'androidx.recyclerview:recyclerview:1.1.0'
    compileOnly 'com.alibaba:fastjson:1.2.83'
    compileOnly 'androidx.legacy:legacy-support-v4:1.0.0'
    compileOnly 'androidx.appcompat:appcompat:1.0.0'
    implementation 'com.alibaba:fastjson:1.2.83'
    implementation 'com.facebook.fresco:fresco:1.13.0'
    implementation 'com.squareup.okhttp3:okhttp:3.2.0'
    implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0'
    implementation 'com.google.code.gson:gson:2.8.5'
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

7、前端示例,只展示关键代码

<script>
let testModule = uni.requireNativePlugin("TestModule")
export default {
		components: {},
		methods: {
				writeFunc() {
					testModule.writeFunc({
							xx:this.formData.xx
					},
						(ret) => {
							//这里的ret就是前面返回的值,直接取
							console.log(ret)
							})
			},
			readFunc() {
					testModule.readFunc({
							xx:this.formData.xx
					},
						(ret) => {
							//这里的ret就是前面返回的值,直接取
							console.log(ret)
							})
			}
}
}
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

8、原生安卓打包成SDK供uniapp集成使用,将以下打包成功的.aar文件放到uniapp工程里。有两种打包方式,第一种是把安卓原生打包成SDK放到uniapp里面调用(推荐),第二种是把uniapp打包成安卓基座,导入到安卓原生代码里进行打包,比较麻烦一点。
在这里插入图片描述
在这里插入图片描述
把导包文件放到uniapp此目录里,没有目录可以创建,不知道原理的可以去研究研究
在这里插入图片描述


总结

1、各位朋友,请聚焦在具体的调用原生安卓逻辑上面,关于怎么打包可自行去搜索相关文章,这里就不过多描述(主要是步骤太多太麻烦了)
2、在此基础上还可以延伸至其他领域,比如刷工牌登录系统、门禁、物料标签等等
3、如果有不明白的地方可留言,我空余时间会尽自己所能给大家解答,谢谢大家!

来自一个被编程耽搁的健身教练编写于公元2024年5月14日

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/922084?site
推荐阅读
相关标签
  

闽ICP备14008679号