NFC介绍
近场通信又称近距离无线通信,是一种短距离的高频无线通信技术,允许电子设备之间进行非接触式点对点数据传输,交换数据。这个技术由免接触式射频识别(RFID)演变而来,由飞利浦和索尼共同研制开发,其基础是RFID及互连技术。近场通信是一种短距高频的无线电技术,在13.56MHz频率运行于20厘米距离内。其传输速度有106 Kbit/秒、212 Kbit/秒或者424 Kbit/秒三种。
近场通信技术主要特征如下:
(1)用于近距离(10cm以内)安全通信的无线通信技术。
(2)射频频率:13.56MHz。
(3)射频兼容:ISO 14443,ISO 15693,Felica标准。
(4)数据传输速度:106kbit/s,212 kbit/s,424kbit/s。
代码区
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.nfc">
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".PackageListActivity"></activity>
<activity android:name=".MainActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity
package com.example.nfc;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.content.Intent;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Settings;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import java.io.IOException;
import java.nio.charset.Charset;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE =0x1 ;
private NfcAdapter nfcAdapter;
private String packageName;
private PendingIntent pi;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nfcAdapter=NfcAdapter.getDefaultAdapter(this);
//
if (nfcAdapter==null){
Toast.makeText(MainActivity.this,"设备不支持NFC功能",Toast.LENGTH_SHORT).show();
finish();
}
//判断设备是否打开NFC功能
if (!nfcAdapter.isEnabled()){
Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS);
startActivity(intent);
}
pi=PendingIntent.getActivity(this,0,new Intent(this,getClass()),0);
}
public void selectStartAppClick(View v){
Intent intent=new Intent(this,PackageListActivity.class);
startActivityForResult(intent,REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==REQUEST_CODE && resultCode==RESULT_OK){
packageName=data.getStringExtra("packageName");
System.out.println(packageName);
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (isRead){
read(intent);
}else {
write(intent);
}
}
/**
* 读取NFC标签的数据进行解析
* @param intent
*/
private void read(Intent intent){
Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag==null){
return;
}
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())){
Parcelable[] data=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (data!=null){
NdefMessage[] ndefMessages=new NdefMessage[data.length];
for (int i=0;i<ndefMessages.length;i++){
ndefMessages[i]= (NdefMessage) data[i];
NdefRecord[] records=ndefMessages[i].getRecords();
String package_name=new String(records[0].getPayload());
String flag=new String(records[1].getPayload());
//打开蓝牙
if ("1".equals(flag)){
BluetoothAdapter bluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
bluetoothAdapter.enable();
}
//根据包名运行程序
Intent startApp=this.getPackageManager().getLaunchIntentForPackage(package_name);
startActivity(startApp);
}
}
}
}
/**
* 把数据写入NFC标签
* @param intent
*/
public void write(Intent intent){
Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag==null){
return;
}
//写入数据
//启动指定的应用程序
// NdefRecord[] recodes=new NdefRecord[]{NdefRecord.createApplicationRecord(packageName)};
//打开URI
// NdefRecord[] recodes=new NdefRecord[]{NdefRecord.createUri("www.baidu.com")};
NdefRecord[] records=new NdefRecord[2];
records[0]=new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,new byte[]{0},packageName.getBytes(Charset.forName("gb2312")));
records[1]=new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,new byte[]{0},"1".getBytes(Charset.forName("gb2312")));
// NdefMessage ndefMessage=new NdefMessage(recodes);
NdefMessage ndefMessage=new NdefMessage(records);
Ndef ndef=Ndef.get(tag);
if (ndef!=null){
try {
ndef.connect();
if (ndef.isWritable()){
int size=ndefMessage.toByteArray().length;
if (ndef.getMaxSize()>size){
ndef.writeNdefMessage(ndefMessage);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
}else {
try {
NdefFormatable ndefFormatable=NdefFormatable.get(tag);
if (ndefFormatable!=null) {
ndefFormatable.connect();
ndefFormatable.format(ndefMessage);//格式化并写入数据
}
} catch (IOException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
}
Toast.makeText(MainActivity.this,"写入成功",Toast.LENGTH_SHORT).show();
}
@Override
protected void onResume() {
super.onResume();
if (nfcAdapter!=null){
//设置当前程序为优先处理NFC的程序
nfcAdapter.enableForegroundDispatch(this,pi,null,null);
}
}
@Override
protected void onPause() {
super.onPause();
if (nfcAdapter!=null){
//取消设置当前程序为优先处理NFC的程序
nfcAdapter.disableForegroundDispatch(this);
}
}
private boolean isRead=true;//true为读取,false为写入
//写入状态
public void writeClick(View v){
isRead=false;
Toast.makeText(MainActivity.this, "当前为写入状态", Toast.LENGTH_SHORT).show();
}
public void readClick(View v){
isRead=true;
Toast.makeText(MainActivity.this, "当前为读取状态", Toast.LENGTH_SHORT).show();
}
}
PackageListActivity
package com.example.nfc;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.List;
public class PackageListActivity extends Activity implements AdapterView.OnItemClickListener {
private ListView packageList;
private List<AppInfo> list=new ArrayList<>();
private MyAdapter myAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_package_list);
packageList=findViewById(R.id.listView);
packageList.setOnItemClickListener(this);
PackageManager pm=getPackageManager();
List<PackageInfo> packageInfos=pm.getInstalledPackages(PackageManager.GET_ACTIVITIES);
for (PackageInfo p:packageInfos){
AppInfo appInfo=new AppInfo();
appInfo.appname=p.applicationInfo.loadLabel(pm).toString();
appInfo.packagename=p.packageName;
appInfo.versionName=p.versionName;
appInfo.versionCode=p.versionCode;
appInfo.appicon=p.applicationInfo.loadIcon(getPackageManager());
list.add(appInfo);
}
myAdapter=new MyAdapter();
packageList.setAdapter(myAdapter);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
AppInfo appInfo=list.get(position);
Intent data=new Intent();
data.putExtra("packageName",appInfo.packagename);
setResult(RESULT_OK,data);
finish();
}
private class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh=null;
if (convertView==null){
convertView=getLayoutInflater().inflate(R.layout.list_item_layout,null);
vh=new ViewHolder();
vh.imageView_logo=convertView.findViewById(R.id.imageView2_logo);
vh.textView_name=convertView.findViewById(R.id.textView_name);
convertView.setTag(vh);
}else {
vh= (ViewHolder) convertView.getTag();
AppInfo info=list.get(position);
vh.imageView_logo.setImageDrawable(info.appicon);
vh.textView_name.setText(info.appname);
}
return convertView;
}
class ViewHolder{
ImageView imageView_logo;
TextView textView_name;
}
}
}
AppInfo
package com.example.nfc;
import android.graphics.drawable.Drawable;
public class AppInfo {
int versionCode=0;//名称
String appname="";//包
String packagename="";
String versionName="";//图标
Drawable appicon=null;
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">
<Button
android:id="@+id/button_select_app"
android:layout_width="170dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginStart="0dp"
android:onClick="selectStartAppClick"
android:layout_marginTop="0dp"
android:text="选择要启动的程序" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/button_select_app"
android:layout_alignParentStart="true"
android:layout_marginStart="0dp"
android:scaleType="centerCrop"
app:srcCompat="@mipmap/nfc" />
<Button
android:id="@+id/button_write"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:onClick="writeClick"
android:layout_toEndOf="@+id/button_select_app"
android:text="写入标签" />
<Button
android:id="@+id/button3"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="0dp"
android:onClick="readClick"
android:layout_marginEnd="3dp"
android:layout_toEndOf="@+id/button_write"
android:text="Button" />
</RelativeLayout>
activity_package_list.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".PackageListActivity">
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/listView"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true">
</ListView>
</RelativeLayout>
list_item_layout.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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/imageView2_logo"
android:layout_width="19dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:srcCompat="@mipmap/ic_launcher" />
<TextView
android:id="@+id/textView_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="loading" />
</LinearLayout>
由于测试需要准备好NFC标签之类的东西,某宝上就有,需要的可以考虑一下,还是挺便宜的。便宜的1块钱不到。