├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ricky │ │ └── nfc │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── ricky │ │ │ └── nfc │ │ │ ├── MainActivity.java │ │ │ ├── activity │ │ │ ├── ReadMUActivity.java │ │ │ ├── ReadTextActivity.java │ │ │ ├── ReadUriActivity.java │ │ │ ├── RunAppActivity.java │ │ │ ├── RunUrlActivity.java │ │ │ ├── WriteMUActivity.java │ │ │ ├── WriteTextActivity.java │ │ │ └── WriteUriActivity.java │ │ │ ├── base │ │ │ └── BaseNfcActivity.java │ │ │ └── tools │ │ │ └── UriPrefix.java │ └── res │ │ ├── drawable │ │ ├── nfc_read.jpg │ │ ├── nfc_run.jpg │ │ └── nfc_write.jpg │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_read_mu.xml │ │ ├── activity_read_text.xml │ │ ├── activity_read_uri.xml │ │ ├── activity_run_app.xml │ │ ├── activity_run_url.xml │ │ ├── activity_write_mu.xml │ │ ├── activity_write_text.xml │ │ └── activity_write_uri.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── ricky │ └── nfc │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nfc-Android 2 | Android Nfc技术使用详解,具体详情可查看[文章地址](http://www.jianshu.com/p/e89cc9bba8a6) 3 | 4 | NFC是Near Field Communication缩写,即`近距离无线通讯技术`。可以在移动设备、消费类电子产品、PC 和智能控件工具间进行近距离无线通信。简单一点说,nfc功能是什么?nfc功能有什么用?其实NFC提供了一种简单、触控式的解决方案,可以让消费者简单直观地交换信息、访问内容与服务。`NFC技术允许电子设备之间进行非接触式点对点数据传输`,在十厘米(3.9英吋)内,交换数据,其传输速度有106Kbit/秒、212Kbit/秒或者424Kbit/秒三种。接下来我们更加详细的来了解一下nfc的应用 5 | 6 | 7 | 8 | * 由飞利浦公司和索尼公司共同开发的NFC是一种非接触式识别和互联技术 9 | 10 | ![](http://upload-images.jianshu.io/upload_images/5443336-d3a5aa356f50cd57.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 11 | 12 | ### 一、nfc是什么,它的工作模式? 13 | NFC工作模式主要有三种工作模式,分别是卡模式(Card emulation)、点对点模式(P2P mode)和读卡器模式(Reader/writer mode)。 14 | 15 | #### (1)读卡器模式 16 | 17 | 数据在NFC芯片中,可以简单理解成“刷标签”。本质上就是通过支持NFC的手机或其它电子设备从带有NFC芯片的标签、贴纸、名片等媒介中读写信息。通常NFC标签是不需要外部供电的。当支持NFC的外设向NFC读写数据时,它会发送某种磁场,而这个磁场会自动的向NFC标签供电 18 | 19 | #### (2)仿真卡模式 20 | 数据在支持NFC的手机或其它电子设备中,可以简单理解成“刷手机”。本质上就是将支持NFC的手机或其它电子设备当成借记卡、公交卡、门禁卡等IC卡使用。基本原理是将相应IC卡中的信息凭证封装成数据包存储在支持NFC的外设中 。在使用时还需要一个NFC射频器(相当于刷卡器)。将手机靠近NFC射频器,手机就会接收到NFC射频器发过来的信号,在通过一系列复杂的验证后,将IC卡的相应信息传入NFC射频器,最后这些IC卡数据会传入NFC射频器连接的电脑,并进行相应的处理(如电子转帐、开门等操作)。 21 | 22 | #### (3)点对点模式 23 | 24 | 该模式与蓝牙、红外差不多,用于不同NFC设备之间进行数据交换,不过这个模式已经没有有“刷”的感觉了。其有效距离一般不能超过4厘米,但传输建立速度要比红外和蓝牙技术快很多,传输速度比红外块得多,如过双方都使用Android4.2,NFC会直接利用蓝牙传输。这种技术被称为AndroidBeam。所以使用androidBeam传输数据的两部设备不再限于4厘米之内 25 | 26 | NFC、蓝牙和红外之间的差异 27 | ![](http://upload-images.jianshu.io/upload_images/5443336-a02d3bde35fa7d5d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 28 | 29 | ### 二、Android对NFC的支持 30 | 不同的NFC标签之间差异很大,有的只支持简单的读写操作,有时还会采用支持一次性写入的芯片,将NFC标签设计成只读的。当然,也存在一些复杂的NFC标签,例如,有一些NFC标签可以通过硬件加密的方式限制对某一区域的访问。还有一些标签自带操作环境,允许NFC设备与这些标签进行更复杂的交互。这些标签中的数据也会采用不同的格式。但Android SDK API主要支持NFC论坛标准(Forum Standard),这种标准被称为NDEF(NFC Data Exchange Format,NFC数据交换格式)。 31 | 32 | NDEF格式其实就类似于硬盘的NTFS,下面我们看一下NDEF数据: 33 | 34 | #### (1)NDEF数据的操作 35 | Android SDK API支持如下3种NDEF数据的操作: 36 | 37 | * 1)从NFC标签读取NDEF格式的数据 38 | * 2)向NFC标签写入NDEF格式的数据 39 | * 3)通过Android Beam技术将NDEF数据发送到另一部NFC设备 40 | 41 | 用于描述NDEF格式数据的两个类: 42 | 43 | * 1)NdefMessage:描述NDEF格式的信息,实际上我们写入NFC标签的就是NdefMessage对象。 44 | * 2)NdefRecord:描述NDEF信息的一个信息段,一个NdefMessage可能包含一个或者多个NdefRecord。 45 | 46 | NdefMessage和NdefRecord是Android NFC技术的核心类,无论读写NDEF格式的NFC标签,还是通过Android Beam技术传递Ndef格式的数据,都需要这两个类。 47 | 48 | #### (2)非NDEF数据的操作 49 | 对于某些特殊需求,可能要存任意的数据,对于这些数据,我们就需要自定义格式。这些数据格式实际上就是普通的字节流,至于字节流中的数据代表什么,就由开发人员自己定义了。 50 | 51 | #### (3)编写NFC程序的基本步骤 52 | * 1)设置权限,限制Android版本、安装的设备: 53 | 54 | ![](http://upload-images.jianshu.io/upload_images/5443336-02ea26579ecb2e80.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 55 | 56 | * 2)定义可接收Tag的Activity,配置一下launchMode属性,处理NFC的Activity都要设置launchMode属性为singleTop或者singleTask,保证activty唯一实例 57 | 58 | ![](http://upload-images.jianshu.io/upload_images/5443336-6d589d8e59e8083d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 59 | 60 | ### 三、实战使用NFC标签 61 | #### (1)利用NFC标签让Android自动运行程序 62 | 场景是这样的:现将应用程序的包写到NFC程序上,然后我们将NFC标签靠近Android手机,手机就会自动运行包所对应的程序,这个是NFC比较基本的一个应用。下面以贴近标签自动运行Android自带的“短信”为例。 63 | 64 | 向NFC标签写入数据一般分为三步: 65 | 66 | * 1)获取Tag对象 67 | 68 | ![](http://upload-images.jianshu.io/upload_images/5443336-13ca866b33394118.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 69 | 70 | * 2)判断NFC标签的数据类型(通过Ndef.get方法) 71 | * 3)写入数据 72 | 73 | ![](http://upload-images.jianshu.io/upload_images/5443336-06b126d1bf203a48.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 74 | 75 | 操作步骤,实际运行效果如下: 76 | 77 | 点击自动打开短信界面或百度页面,进入对应Activity,将NFC标签贴近手机背面,提示写入成功。返回主界面,再将NFC标签贴近手机背面,便能看到自动打开短信或者打开百度页面。 78 | 79 | * 应用主界面: 80 | 81 | ![](http://upload-images.jianshu.io/upload_images/5443336-6e799fa3a8598b77.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 82 | 83 | * 数据写入界面: 84 | 85 | ![](http://upload-images.jianshu.io/upload_images/5443336-5b65998645199bc6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 86 | 87 | * 扫描NFC标签后跳转页面 88 | 89 | ![](http://upload-images.jianshu.io/upload_images/5443336-ac73588141ca844a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 90 | 91 | ### 四、NDEF文本格式深度解析 92 | 93 | 获取NFC标签中的数据要通过 NdefRecord.getPayload 方法完成。当然,在处理这些数据之前,最好判断一下NdefRecord对象中存储的是不是NDEF文本格式数据。 94 | 95 | #### (1)判断数据是否为NDEF格式 96 | * 1)TNF(类型名格式,Type Name Format)必须是NdefRecord.TNF_WELL_KNOWN。 97 | * 2)可变的长度类型必须是NdefRecord.RTD_TEXT。 98 | 99 | 如果这两个标准同时满足,那么就为NDEF格式 100 | 101 | #### (2)NDEF文本格式规范 102 | 不管什么格式的数据本质上都是由一些字节组成的。对于NDEF文本格式来说,这些数据的第1个字节描述了数据的状态,然后若干个字节描述文本的语言编码,最后剩余字节表示文本数据。这些数据格式由NFC Forum的相关规范定义,可以通过 http://members.nfc-forum.org/specs/spec_dashboard 下载相关的规范。 103 | 104 | 下面这两张表是规范中 3.2节 相对重要的翻译部分: 105 | 106 | * NDEF文本数据格式 107 | 108 | ![](http://upload-images.jianshu.io/upload_images/5443336-4ca1bae404f85a49.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 109 | 110 | * 状态字节编码格式 111 | 112 | ![](http://upload-images.jianshu.io/upload_images/5443336-8507380e27ef4496.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 113 | 114 | 实现NFC标签中的文本数据的读写操作: 115 | 116 | * 写文本数据核心代码,具体可查阅项目中代码WriteTextActivity类 117 | 118 | ![](http://upload-images.jianshu.io/upload_images/5443336-24f1eaf321c6bfbe.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 119 | 120 | * 读文本数据核心代码,具体可查阅项目中代码ReadTextActivity类 121 | 122 | ![](http://upload-images.jianshu.io/upload_images/5443336-bc192aaa34e5d5af.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 123 | 124 | 点击写NFC标签中的文本数据,跳转到对应的Activity,将NFC标签卡贴近手机,写入成功后会提示,再退回主页面,选择读文本数据,便可读取。 125 | 126 | * 数据写入界面 127 | 128 | ![](http://upload-images.jianshu.io/upload_images/5443336-caffd6bf63a3cae2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 129 | 130 | * 数据读取界面 131 | 132 | ![](http://upload-images.jianshu.io/upload_images/5443336-d1e503f2dda83c40.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 133 | 134 | ### 五、NDEF Uri格式存储(操作步骤如上图,具体实现可查阅项目代码) 135 | 136 | ### 六、非NDEF格式(操作步骤如上图,具体实现查阅项目代码) 137 | 138 | MifareUltralight数据格式:将NFC标签的存储区域分为16个页,每一个页可以存储4个字节,一个可存储64个字节(512位)。页码从0开始(0至15)。前4页(0至3)存储了NFC标签相关的信息(如NFC标签的序列号、控制位等)。从第5页开始存储实际的数据(4至15页)。使用MifareUltralight.get方法获取MifareUltralight对象,然后调用MifareUltralight.connect方法进行连接,并使用MifareUltralight.writePage方法每次写入1页(4个字节)。 139 | 也可以使用MifareUltralight.readPages方法每次连续读取4页。如果读取的页的序号超过15,则从头开始读。例如,从第15页(序号为14)开始读。readPages方法会读取14、15、0、1页的数据。 140 | 141 | 142 | * 此为本次测试所使用设备,手机:小米5 NFC标签卡:淘宝可购买 143 | 144 | ![](http://upload-images.jianshu.io/upload_images/5443336-35393841d4ae6d61.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "com.ricky.nfc" 8 | minSdkVersion 18 9 | targetSdkVersion 26 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:26.+' 28 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 29 | testCompile 'junit:junit:4.12' 30 | } 31 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in E:\Android\SDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/ricky/nfc/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.ricky.nfc", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 28 | 31 | 34 | 37 | 40 | 43 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc; 2 | 3 | import android.content.Intent; 4 | import android.nfc.NfcAdapter; 5 | import android.os.Bundle; 6 | import android.view.View; 7 | import android.widget.AdapterView; 8 | import android.widget.ArrayAdapter; 9 | import android.widget.ListView; 10 | import android.widget.TextView; 11 | import com.ricky.nfc.activity.ReadMUActivity; 12 | import com.ricky.nfc.activity.ReadTextActivity; 13 | import com.ricky.nfc.activity.ReadUriActivity; 14 | import com.ricky.nfc.activity.RunAppActivity; 15 | import com.ricky.nfc.activity.RunUrlActivity; 16 | import com.ricky.nfc.activity.WriteMUActivity; 17 | import com.ricky.nfc.activity.WriteTextActivity; 18 | import com.ricky.nfc.activity.WriteUriActivity; 19 | import com.ricky.nfc.base.BaseNfcActivity; 20 | 21 | public class MainActivity extends BaseNfcActivity { 22 | private TextView ifo_NFC; 23 | private static final String[] strs = new String[]{ 24 | "自动打开短信界面", 25 | "自动打开百度页面", 26 | "读NFC标签中的文本数据", 27 | "写NFC标签中的文本数据", 28 | "读NFC标签中的Uri数据", 29 | "写NFC标签中的Uri数据", 30 | "读NFC标签非NDEF格式的数据", 31 | "写NFC标签非NDEF格式的数据" 32 | }; 33 | 34 | @Override 35 | public void onCreate(Bundle savedInstanceState) { 36 | super.onCreate(savedInstanceState); 37 | setContentView(R.layout.activity_main); 38 | ifo_NFC = (TextView) findViewById(R.id.ifo_NFC); 39 | // NFC适配器,所有的关于NFC的操作从该适配器进行 40 | mNfcAdapter = NfcAdapter.getDefaultAdapter(this); 41 | if (!ifNFCUse()) { 42 | return; 43 | } 44 | ListView listView = (ListView) findViewById(R.id.listview); 45 | listView.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, strs)); 46 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 47 | @Override 48 | public void onItemClick(AdapterView parent, View view, int position, long id) { 49 | switchActivity(position); 50 | } 51 | }); 52 | } 53 | 54 | private void switchActivity(int position) { 55 | switch (position) { 56 | case 0: //自动打开短信界面 57 | startActivity(new Intent(this, RunAppActivity.class)); 58 | break; 59 | case 1: //自动打开百度页面 60 | startActivity(new Intent(this, RunUrlActivity.class)); 61 | break; 62 | case 2: //读NFC标签中的文本数据 63 | startActivity(new Intent(this, ReadTextActivity.class)); 64 | break; 65 | case 3: //写NFC标签中的文本数据 66 | startActivity(new Intent(this, WriteTextActivity.class)); 67 | break; 68 | case 4: //读NFC标签中的Uri数据 69 | startActivity(new Intent(this, ReadUriActivity.class)); 70 | break; 71 | case 5: //写NFC标签中的Uri数据 72 | startActivity(new Intent(this, WriteUriActivity.class)); 73 | break; 74 | case 6: //读NFC标签非NDEF格式的数据 75 | startActivity(new Intent(this, ReadMUActivity.class)); 76 | break; 77 | case 7: //写NFC标签非NDEF格式的数据 78 | startActivity(new Intent(this, WriteMUActivity.class)); 79 | break; 80 | default: 81 | break; 82 | } 83 | } 84 | 85 | /** 86 | * 检测工作,判断设备的NFC支持情况 87 | * 88 | * @return 89 | */ 90 | protected Boolean ifNFCUse() { 91 | if (mNfcAdapter == null) { 92 | ifo_NFC.setText("设备不支持NFC!"); 93 | return false; 94 | } 95 | if (mNfcAdapter != null && !mNfcAdapter.isEnabled()) { 96 | ifo_NFC.setText("请在系统设置中先启用NFC功能!"); 97 | return false; 98 | } 99 | return true; 100 | } 101 | } 102 | 103 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/ReadMUActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.nfc.NfcAdapter; 5 | import android.nfc.Tag; 6 | import android.nfc.tech.MifareUltralight; 7 | import android.os.Bundle; 8 | import android.widget.Toast; 9 | import com.ricky.nfc.R; 10 | import com.ricky.nfc.base.BaseNfcActivity; 11 | import java.nio.charset.Charset; 12 | 13 | /** 14 | * Author:Created by Ricky on 2017/8/25. 15 | * Email:584182977@qq.com 16 | * Description: 17 | */ 18 | public class ReadMUActivity extends BaseNfcActivity { 19 | @Override 20 | public void onCreate(Bundle savedInstanceState) { 21 | super.onCreate(savedInstanceState); 22 | setContentView(R.layout.activity_read_mu); 23 | } 24 | 25 | @Override 26 | public void onNewIntent(Intent intent) { 27 | Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 28 | String[] techList = tag.getTechList(); 29 | boolean haveMifareUltralight = false; 30 | for (String tech : techList) { 31 | if (tech.indexOf("MifareUltralight") >= 0) { 32 | haveMifareUltralight = true; 33 | break; 34 | } 35 | } 36 | if (!haveMifareUltralight) { 37 | Toast.makeText(this, "不支持MifareUltralight数据格式", Toast.LENGTH_SHORT).show(); 38 | return; 39 | } 40 | String data = readTag(tag); 41 | if (data != null) 42 | Toast.makeText(this, data, Toast.LENGTH_SHORT).show(); 43 | } 44 | 45 | public String readTag(Tag tag) { 46 | MifareUltralight ultralight = MifareUltralight.get(tag); 47 | try { 48 | ultralight.connect(); 49 | byte[] data = ultralight.readPages(4); 50 | return new String(data, Charset.forName("GB2312")); 51 | } catch (Exception e) { 52 | } finally { 53 | try { 54 | ultralight.close(); 55 | } catch (Exception e) { 56 | } 57 | } 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/ReadTextActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.nfc.NdefMessage; 5 | import android.nfc.NdefRecord; 6 | import android.nfc.NfcAdapter; 7 | import android.nfc.Tag; 8 | import android.nfc.tech.Ndef; 9 | import android.os.Bundle; 10 | import android.os.Parcelable; 11 | import android.widget.TextView; 12 | import com.ricky.nfc.R; 13 | import com.ricky.nfc.base.BaseNfcActivity; 14 | import java.util.Arrays; 15 | 16 | /** 17 | * Author:Created by Ricky on 2017/8/25. 18 | * Email:584182977@qq.com 19 | * Description: 20 | */ 21 | public class ReadTextActivity extends BaseNfcActivity { 22 | private TextView mNfcText; 23 | private String mTagText; 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_read_text); 29 | mNfcText = (TextView) findViewById(R.id.tv_nfctext); 30 | } 31 | 32 | @Override 33 | public void onNewIntent(Intent intent) { 34 | //1.获取Tag对象 35 | Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 36 | //2.获取Ndef的实例 37 | Ndef ndef = Ndef.get(detectedTag); 38 | mTagText = ndef.getType() + "\nmaxsize:" + ndef.getMaxSize() + "bytes\n\n"; 39 | readNfcTag(intent); 40 | mNfcText.setText(mTagText); 41 | } 42 | 43 | /** 44 | * 读取NFC标签文本数据 45 | */ 46 | private void readNfcTag(Intent intent) { 47 | if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { 48 | Parcelable[] rawMsgs = intent.getParcelableArrayExtra( 49 | NfcAdapter.EXTRA_NDEF_MESSAGES); 50 | NdefMessage msgs[] = null; 51 | int contentSize = 0; 52 | if (rawMsgs != null) { 53 | msgs = new NdefMessage[rawMsgs.length]; 54 | for (int i = 0; i < rawMsgs.length; i++) { 55 | msgs[i] = (NdefMessage) rawMsgs[i]; 56 | contentSize += msgs[i].toByteArray().length; 57 | } 58 | } 59 | try { 60 | if (msgs != null) { 61 | NdefRecord record = msgs[0].getRecords()[0]; 62 | String textRecord = parseTextRecord(record); 63 | mTagText += textRecord + "\n\ntext\n" + contentSize + " bytes"; 64 | } 65 | } catch (Exception e) { 66 | } 67 | } 68 | } 69 | 70 | /** 71 | * 解析NDEF文本数据,从第三个字节开始,后面的文本数据 72 | * 73 | * @param ndefRecord 74 | * @return 75 | */ 76 | public static String parseTextRecord(NdefRecord ndefRecord) { 77 | /** 78 | * 判断数据是否为NDEF格式 79 | */ 80 | //判断TNF 81 | if (ndefRecord.getTnf() != NdefRecord.TNF_WELL_KNOWN) { 82 | return null; 83 | } 84 | //判断可变的长度的类型 85 | if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) { 86 | return null; 87 | } 88 | try { 89 | //获得字节数组,然后进行分析 90 | byte[] payload = ndefRecord.getPayload(); 91 | //下面开始NDEF文本数据第一个字节,状态字节 92 | //判断文本是基于UTF-8还是UTF-16的,取第一个字节"位与"上16进制的80,16进制的80也就是最高位是1, 93 | //其他位都是0,所以进行"位与"运算后就会保留最高位 94 | String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" : "UTF-16"; 95 | //3f最高两位是0,第六位是1,所以进行"位与"运算后获得第六位 96 | int languageCodeLength = payload[0] & 0x3f; 97 | //下面开始NDEF文本数据第二个字节,语言编码 98 | //获得语言编码 99 | String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII"); 100 | //下面开始NDEF文本数据后面的字节,解析出文本 101 | String textRecord = new String(payload, languageCodeLength + 1, 102 | payload.length - languageCodeLength - 1, textEncoding); 103 | return textRecord; 104 | } catch (Exception e) { 105 | throw new IllegalArgumentException(); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/ReadUriActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.nfc.NdefMessage; 6 | import android.nfc.NdefRecord; 7 | import android.nfc.NfcAdapter; 8 | import android.nfc.Tag; 9 | import android.nfc.tech.Ndef; 10 | import android.os.Bundle; 11 | import android.os.Parcelable; 12 | import android.util.Log; 13 | import android.widget.TextView; 14 | 15 | import com.ricky.nfc.R; 16 | import com.ricky.nfc.base.BaseNfcActivity; 17 | import com.ricky.nfc.tools.UriPrefix; 18 | import java.nio.charset.Charset; 19 | import java.util.Arrays; 20 | /** 21 | * Author:Created by Ricky on 2017/8/25. 22 | * Email:584182977@qq.com 23 | * Description: 24 | */ 25 | public class ReadUriActivity extends BaseNfcActivity { 26 | private TextView mNfcText; 27 | private String mTagText; 28 | 29 | @Override 30 | public void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_read_uri); 33 | mNfcText = (TextView) findViewById(R.id.tv_nfctext); 34 | } 35 | 36 | @Override 37 | public void onNewIntent(Intent intent) { 38 | //获取Tag对象 39 | Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 40 | //获取Ndef的实例 41 | Ndef ndef = Ndef.get(detectedTag); 42 | mTagText = ndef.getType() + "\n max size:" + ndef.getMaxSize() + " bytes\n\n"; 43 | readNfcTag(intent); 44 | mNfcText.setText(mTagText); 45 | } 46 | 47 | /** 48 | * 读取NFC标签Uri 49 | */ 50 | private void readNfcTag(Intent intent) { 51 | if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { 52 | Parcelable[] rawMsgs = intent.getParcelableArrayExtra( 53 | NfcAdapter.EXTRA_NDEF_MESSAGES); 54 | NdefMessage ndefMessage = null; 55 | int contentSize = 0; 56 | if (rawMsgs != null) { 57 | if (rawMsgs.length > 0) { 58 | ndefMessage = (NdefMessage) rawMsgs[0]; 59 | contentSize = ndefMessage.toByteArray().length; 60 | } else { 61 | return; 62 | } 63 | } 64 | try { 65 | NdefRecord ndefRecord = ndefMessage.getRecords()[0]; 66 | Log.i("JAVA", ndefRecord.toString()); 67 | Uri uri = parse(ndefRecord); 68 | Log.i("JAVA", "uri:" + uri.toString()); 69 | mTagText += uri.toString() + "\n\nUri\n" + contentSize + " bytes"; 70 | } catch (Exception e) { 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * 解析NdefRecord中Uri数据 77 | * 78 | * @param record 79 | * @return 80 | */ 81 | public static Uri parse(NdefRecord record) { 82 | short tnf = record.getTnf(); 83 | if (tnf == NdefRecord.TNF_WELL_KNOWN) { 84 | return parseWellKnown(record); 85 | } else if (tnf == NdefRecord.TNF_ABSOLUTE_URI) { 86 | return parseAbsolute(record); 87 | } 88 | throw new IllegalArgumentException("Unknown TNF " + tnf); 89 | } 90 | 91 | /** 92 | * 处理绝对的Uri 93 | * 没有Uri识别码,也就是没有Uri前缀,存储的全部是字符串 94 | * 95 | * @param ndefRecord 描述NDEF信息的一个信息段,一个NdefMessage可能包含一个或者多个NdefRecord 96 | * @return 97 | */ 98 | private static Uri parseAbsolute(NdefRecord ndefRecord) { 99 | //获取所有的字节数据 100 | byte[] payload = ndefRecord.getPayload(); 101 | Uri uri = Uri.parse(new String(payload, Charset.forName("UTF-8"))); 102 | return uri; 103 | } 104 | 105 | /** 106 | * 处理已知类型的Uri 107 | * 108 | * @param ndefRecord 109 | * @return 110 | */ 111 | private static Uri parseWellKnown(NdefRecord ndefRecord) { 112 | //判断数据是否是Uri类型的 113 | if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_URI)) 114 | return null; 115 | //获取所有的字节数据 116 | byte[] payload = ndefRecord.getPayload(); 117 | String prefix = UriPrefix.URI_PREFIX_MAP.get(payload[0]); 118 | byte[] prefixBytes = prefix.getBytes(Charset.forName("UTF-8")); 119 | byte[] fullUri = new byte[prefixBytes.length + payload.length - 1]; 120 | System.arraycopy(prefixBytes, 0, fullUri, 0, prefixBytes.length); 121 | System.arraycopy(payload, 1, fullUri, prefixBytes.length, payload.length - 1); 122 | Uri uri = Uri.parse(new String(fullUri, Charset.forName("UTF-8"))); 123 | return uri; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/RunAppActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.nfc.NdefMessage; 5 | import android.nfc.NdefRecord; 6 | import android.nfc.NfcAdapter; 7 | import android.nfc.Tag; 8 | import android.nfc.tech.Ndef; 9 | import android.nfc.tech.NdefFormatable; 10 | import android.os.Bundle; 11 | import android.widget.Toast; 12 | 13 | import com.ricky.nfc.R; 14 | import com.ricky.nfc.base.BaseNfcActivity; 15 | 16 | 17 | /** 18 | * Author:Created by Ricky on 2017/8/25. 19 | * Email:584182977@qq.com 20 | * Description:打开短信 21 | */ 22 | public class RunAppActivity extends BaseNfcActivity { 23 | private String mPackageName = "com.android.mms";//短信 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_run_app); 29 | } 30 | 31 | @Override 32 | public void onNewIntent(Intent intent) { 33 | if (mPackageName == null) 34 | return; 35 | //1.获取Tag对象 36 | Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 37 | writeNFCTag(detectedTag); 38 | } 39 | 40 | /** 41 | * 往标签写数据的方法 42 | * 43 | * @param tag 44 | */ 45 | public void writeNFCTag(Tag tag) { 46 | if (tag == null) { 47 | return; 48 | } 49 | NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{NdefRecord 50 | .createApplicationRecord(mPackageName)}); 51 | //转换成字节获得大小 52 | int size = ndefMessage.toByteArray().length; 53 | try { 54 | //2.判断NFC标签的数据类型(通过Ndef.get方法) 55 | Ndef ndef = Ndef.get(tag); 56 | //判断是否为NDEF标签 57 | if (ndef != null) { 58 | ndef.connect(); 59 | //判断是否支持可写 60 | if (!ndef.isWritable()) { 61 | return; 62 | } 63 | //判断标签的容量是否够用 64 | if (ndef.getMaxSize() < size) { 65 | return; 66 | } 67 | //3.写入数据 68 | ndef.writeNdefMessage(ndefMessage); 69 | Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); 70 | } else { //当我们买回来的NFC标签是没有格式化的,或者没有分区的执行此步 71 | //Ndef格式类 72 | NdefFormatable format = NdefFormatable.get(tag); 73 | //判断是否获得了NdefFormatable对象,有一些标签是只读的或者不允许格式化的 74 | if (format != null) { 75 | //连接 76 | format.connect(); 77 | //格式化并将信息写入标签 78 | format.format(ndefMessage); 79 | Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); 80 | } else { 81 | Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show(); 82 | } 83 | } 84 | } catch (Exception e) { 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/RunUrlActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.nfc.NdefMessage; 6 | import android.nfc.NdefRecord; 7 | import android.nfc.NfcAdapter; 8 | import android.nfc.Tag; 9 | import android.nfc.tech.Ndef; 10 | import android.nfc.tech.NdefFormatable; 11 | import android.os.Bundle; 12 | import android.widget.Toast; 13 | 14 | import com.ricky.nfc.R; 15 | import com.ricky.nfc.base.BaseNfcActivity; 16 | 17 | 18 | /** 19 | * Author:Created by Ricky on 2017/8/25. 20 | * Email:584182977@qq.com 21 | * Description: 打开网页 22 | */ 23 | public class RunUrlActivity extends BaseNfcActivity { 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_run_url); 28 | } 29 | 30 | @Override 31 | public void onNewIntent(Intent intent) { 32 | //1.获取Tag对象 33 | Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 34 | writeNFCTag(detectedTag); 35 | } 36 | 37 | /** 38 | * 往标签写数据的方法 39 | * 40 | * @param tag 41 | */ 42 | public void writeNFCTag(Tag tag) { 43 | if (tag == null) { 44 | return; 45 | } 46 | NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{NdefRecord 47 | .createUri(Uri.parse("http://www.baidu.com"))}); 48 | //转换成字节获得大小 49 | int size = ndefMessage.toByteArray().length; 50 | try { 51 | //2.判断NFC标签的数据类型(通过Ndef.get方法) 52 | Ndef ndef = Ndef.get(tag); 53 | //判断是否为NDEF标签 54 | if (ndef != null) { 55 | ndef.connect(); 56 | //判断是否支持可写 57 | if (!ndef.isWritable()) { 58 | return; 59 | } 60 | //判断标签的容量是否够用 61 | if (ndef.getMaxSize() < size) { 62 | return; 63 | } 64 | //3.写入数据 65 | ndef.writeNdefMessage(ndefMessage); 66 | Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); 67 | } else { //当我们买回来的NFC标签是没有格式化的,或者没有分区的执行此步 68 | //Ndef格式类 69 | NdefFormatable format = NdefFormatable.get(tag); 70 | //判断是否获得了NdefFormatable对象,有一些标签是只读的或者不允许格式化的 71 | if (format != null) { 72 | //连接 73 | format.connect(); 74 | //格式化并将信息写入标签 75 | format.format(ndefMessage); 76 | Toast.makeText(this, "写入成功", 77 | Toast.LENGTH_SHORT).show(); 78 | } else { 79 | Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show(); 80 | } 81 | } 82 | } catch (Exception e) { 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/WriteMUActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.nfc.NfcAdapter; 5 | import android.nfc.Tag; 6 | import android.nfc.tech.MifareUltralight; 7 | import android.os.Bundle; 8 | import android.widget.Toast; 9 | 10 | import com.ricky.nfc.R; 11 | import com.ricky.nfc.base.BaseNfcActivity; 12 | 13 | import java.nio.charset.Charset; 14 | 15 | /** 16 | * Author:Created by Ricky on 2017/8/25. 17 | * Email:584182977@qq.com 18 | * Description: 19 | */ 20 | public class WriteMUActivity extends BaseNfcActivity { 21 | @Override 22 | public void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_write_mu); 25 | } 26 | 27 | @Override 28 | public void onNewIntent(Intent intent) { 29 | Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 30 | String[] techList = tag.getTechList(); 31 | boolean haveMifareUltralight = false; 32 | for (String tech : techList) { 33 | if (tech.indexOf("MifareUltralight") >= 0) { 34 | haveMifareUltralight = true; 35 | break; 36 | } 37 | } 38 | if (!haveMifareUltralight) { 39 | Toast.makeText(this, "不支持MifareUltralight数据格式", Toast.LENGTH_SHORT).show(); 40 | return; 41 | } 42 | writeTag(tag); 43 | } 44 | 45 | public void writeTag(Tag tag) { 46 | MifareUltralight ultralight = MifareUltralight.get(tag); 47 | try { 48 | ultralight.connect(); 49 | //写入八个汉字,从第五页开始写,中文需要转换成GB2312格式 50 | ultralight.writePage(4, "北京".getBytes(Charset.forName("GB2312"))); 51 | ultralight.writePage(5, "上海".getBytes(Charset.forName("GB2312"))); 52 | ultralight.writePage(6, "广州".getBytes(Charset.forName("GB2312"))); 53 | ultralight.writePage(7, "天津".getBytes(Charset.forName("GB2312"))); 54 | Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); 55 | } catch (Exception e) { 56 | } finally { 57 | try { 58 | ultralight.close(); 59 | } catch (Exception e) { 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/WriteTextActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.nfc.NdefMessage; 5 | import android.nfc.NdefRecord; 6 | import android.nfc.NfcAdapter; 7 | import android.nfc.Tag; 8 | import android.nfc.tech.Ndef; 9 | import android.os.Bundle; 10 | import android.widget.Toast; 11 | 12 | import com.ricky.nfc.R; 13 | import com.ricky.nfc.base.BaseNfcActivity; 14 | 15 | import java.nio.charset.Charset; 16 | import java.util.Locale; 17 | 18 | /** 19 | * Author:Created by Ricky on 2017/8/25. 20 | * Email:584182977@qq.com 21 | * Description: 22 | */ 23 | public class WriteTextActivity extends BaseNfcActivity { 24 | private String mText = "NFC-NewText-123"; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_write_text); 30 | } 31 | 32 | @Override 33 | public void onNewIntent(Intent intent) { 34 | if (mText == null) 35 | return; 36 | //获取Tag对象 37 | Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 38 | NdefMessage ndefMessage = new NdefMessage( 39 | new NdefRecord[]{createTextRecord(mText)}); 40 | boolean result = writeTag(ndefMessage, detectedTag); 41 | if (result) { 42 | Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); 43 | } else { 44 | Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show(); 45 | } 46 | } 47 | 48 | /** 49 | * 创建NDEF文本数据 50 | * 51 | * @param text 52 | * @return 53 | */ 54 | public static NdefRecord createTextRecord(String text) { 55 | byte[] langBytes = Locale.CHINA.getLanguage().getBytes(Charset.forName("US-ASCII")); 56 | Charset utfEncoding = Charset.forName("UTF-8"); 57 | //将文本转换为UTF-8格式 58 | byte[] textBytes = text.getBytes(utfEncoding); 59 | //设置状态字节编码最高位数为0 60 | int utfBit = 0; 61 | //定义状态字节 62 | char status = (char) (utfBit + langBytes.length); 63 | byte[] data = new byte[1 + langBytes.length + textBytes.length]; 64 | //设置第一个状态字节,先将状态码转换成字节 65 | data[0] = (byte) status; 66 | //设置语言编码,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1到langBytes.length的位置 67 | System.arraycopy(langBytes, 0, data, 1, langBytes.length); 68 | //设置文本字节,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1 + langBytes.length 69 | //到textBytes.length的位置 70 | System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length); 71 | //通过字节传入NdefRecord对象 72 | //NdefRecord.RTD_TEXT:传入类型 读写 73 | NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, 74 | NdefRecord.RTD_TEXT, new byte[0], data); 75 | return ndefRecord; 76 | } 77 | 78 | /** 79 | * 写数据 80 | * 81 | * @param ndefMessage 创建好的NDEF文本数据 82 | * @param tag 标签 83 | * @return 84 | */ 85 | public static boolean writeTag(NdefMessage ndefMessage, Tag tag) { 86 | try { 87 | Ndef ndef = Ndef.get(tag); 88 | ndef.connect(); 89 | ndef.writeNdefMessage(ndefMessage); 90 | return true; 91 | } catch (Exception e) { 92 | } 93 | return false; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/activity/WriteUriActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.activity; 2 | 3 | import android.content.Intent; 4 | import android.nfc.NdefMessage; 5 | import android.nfc.NdefRecord; 6 | import android.nfc.NfcAdapter; 7 | import android.nfc.Tag; 8 | import android.nfc.tech.Ndef; 9 | import android.os.Bundle; 10 | import android.widget.Toast; 11 | import com.ricky.nfc.R; 12 | import com.ricky.nfc.base.BaseNfcActivity; 13 | import com.ricky.nfc.tools.UriPrefix; 14 | 15 | /** 16 | * Author:Created by Ricky on 2017/8/25. 17 | * Email:584182977@qq.com 18 | * Description: 19 | */ 20 | public class WriteUriActivity extends BaseNfcActivity { 21 | private String mUri = "http://www.baidu.com"; 22 | 23 | @Override 24 | public void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_write_uri); 27 | } 28 | 29 | public void onNewIntent(Intent intent) { 30 | Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); 31 | NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{createUriRecord(mUri)}); 32 | boolean result = writeTag(ndefMessage, detectedTag); 33 | if (result) { 34 | Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show(); 35 | } else { 36 | Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show(); 37 | } 38 | } 39 | 40 | /** 41 | * 将Uri转成NdefRecord 42 | * 43 | * @param uriStr 44 | * @return 45 | */ 46 | public static NdefRecord createUriRecord(String uriStr) { 47 | byte prefix = 0; 48 | for (Byte b : UriPrefix.URI_PREFIX_MAP.keySet()) { 49 | String prefixStr = UriPrefix.URI_PREFIX_MAP.get(b).toLowerCase(); 50 | if ("".equals(prefixStr)) 51 | continue; 52 | if (uriStr.toLowerCase().startsWith(prefixStr)) { 53 | prefix = b; 54 | uriStr = uriStr.substring(prefixStr.length()); 55 | break; 56 | } 57 | } 58 | byte[] data = new byte[1 + uriStr.length()]; 59 | data[0] = prefix; 60 | System.arraycopy(uriStr.getBytes(), 0, data, 1, uriStr.length()); 61 | NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], data); 62 | return record; 63 | } 64 | 65 | /** 66 | * 写入标签 67 | * 68 | * @param message 69 | * @param tag 70 | * @return 71 | */ 72 | public static boolean writeTag(NdefMessage message, Tag tag) { 73 | int size = message.toByteArray().length; 74 | try { 75 | Ndef ndef = Ndef.get(tag); 76 | if (ndef != null) { 77 | ndef.connect(); 78 | if (!ndef.isWritable()) { 79 | return false; 80 | } 81 | if (ndef.getMaxSize() < size) { 82 | return false; 83 | } 84 | ndef.writeNdefMessage(message); 85 | return true; 86 | } 87 | } catch (Exception e) { 88 | } 89 | return false; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/base/BaseNfcActivity.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.base; 2 | 3 | import android.app.PendingIntent; 4 | import android.content.Intent; 5 | import android.nfc.NfcAdapter; 6 | import android.support.v7.app.AppCompatActivity; 7 | /** 8 | * Author:Created by Ricky on 2017/8/25. 9 | * Email:584182977@qq.com 10 | * Description: 11 | * 子类在onNewIntent方法中进行NFC标签相关操作。 12 | * launchMode设置为singleTop或singelTask,保证Activity的重用唯一 13 | * 在onNewIntent方法中执行intent传递过来的Tag数据 14 | * 将NFC标签卡靠近手机后部(NFC标签卡可网上自行购买) 15 | */ 16 | public class BaseNfcActivity extends AppCompatActivity { 17 | protected NfcAdapter mNfcAdapter; 18 | private PendingIntent mPendingIntent; 19 | 20 | /** 21 | * onCreat->onStart->onResume->onPause->onStop->onDestroy 22 | * 启动Activity,界面可见时. 23 | */ 24 | @Override 25 | protected void onStart() { 26 | super.onStart(); 27 | //此处adapter需要重新获取,否则无法获取message 28 | mNfcAdapter = NfcAdapter.getDefaultAdapter(this); 29 | //一旦截获NFC消息,就会通过PendingIntent调用窗口 30 | mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0); 31 | } 32 | 33 | /** 34 | * 获得焦点,按钮可以点击 35 | */ 36 | @Override 37 | public void onResume() { 38 | super.onResume(); 39 | //设置处理优于所有其他NFC的处理 40 | if (mNfcAdapter != null) 41 | mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null); 42 | } 43 | 44 | /** 45 | * 暂停Activity,界面获取焦点,按钮可以点击 46 | */ 47 | @Override 48 | public void onPause() { 49 | super.onPause(); 50 | //恢复默认状态 51 | if (mNfcAdapter != null) 52 | mNfcAdapter.disableForegroundDispatch(this); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/ricky/nfc/tools/UriPrefix.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc.tools; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Author:Created by Ricky on 2017/8/25. 8 | * Email:584182977@qq.com 9 | * Description:地址前缀 10 | */ 11 | public class UriPrefix { 12 | public static final Map URI_PREFIX_MAP = new HashMap<>(); 13 | 14 | // 预先定义已知Uri前缀 15 | static { 16 | URI_PREFIX_MAP.put((byte) 0x00, ""); 17 | URI_PREFIX_MAP.put((byte) 0x01, "http://www."); 18 | URI_PREFIX_MAP.put((byte) 0x02, "https://www."); 19 | URI_PREFIX_MAP.put((byte) 0x03, "http://"); 20 | URI_PREFIX_MAP.put((byte) 0x04, "https://"); 21 | URI_PREFIX_MAP.put((byte) 0x05, "tel:"); 22 | URI_PREFIX_MAP.put((byte) 0x06, "mailto:"); 23 | URI_PREFIX_MAP.put((byte) 0x07, "ftp://anonymous:anonymous@"); 24 | URI_PREFIX_MAP.put((byte) 0x08, "ftp://ftp."); 25 | URI_PREFIX_MAP.put((byte) 0x09, "ftps://"); 26 | URI_PREFIX_MAP.put((byte) 0x0A, "sftp://"); 27 | URI_PREFIX_MAP.put((byte) 0x0B, "smb://"); 28 | URI_PREFIX_MAP.put((byte) 0x0C, "nfs://"); 29 | URI_PREFIX_MAP.put((byte) 0x0D, "ftp://"); 30 | URI_PREFIX_MAP.put((byte) 0x0E, "dav://"); 31 | URI_PREFIX_MAP.put((byte) 0x0F, "news:"); 32 | URI_PREFIX_MAP.put((byte) 0x10, "telnet://"); 33 | URI_PREFIX_MAP.put((byte) 0x11, "imap:"); 34 | URI_PREFIX_MAP.put((byte) 0x12, "rtsp://"); 35 | URI_PREFIX_MAP.put((byte) 0x13, "urn:"); 36 | URI_PREFIX_MAP.put((byte) 0x14, "pop:"); 37 | URI_PREFIX_MAP.put((byte) 0x15, "sip:"); 38 | URI_PREFIX_MAP.put((byte) 0x16, "sips:"); 39 | URI_PREFIX_MAP.put((byte) 0x17, "tftp:"); 40 | URI_PREFIX_MAP.put((byte) 0x18, "btspp://"); 41 | URI_PREFIX_MAP.put((byte) 0x19, "btl2cap://"); 42 | URI_PREFIX_MAP.put((byte) 0x1A, "btgoep://"); 43 | URI_PREFIX_MAP.put((byte) 0x1B, "tcpobex://"); 44 | URI_PREFIX_MAP.put((byte) 0x1C, "irdaobex://"); 45 | URI_PREFIX_MAP.put((byte) 0x1D, "file://"); 46 | URI_PREFIX_MAP.put((byte) 0x1E, "urn:epc:id:"); 47 | URI_PREFIX_MAP.put((byte) 0x1F, "urn:epc:tag:"); 48 | URI_PREFIX_MAP.put((byte) 0x20, "urn:epc:pat:"); 49 | URI_PREFIX_MAP.put((byte) 0x21, "urn:epc:raw:"); 50 | URI_PREFIX_MAP.put((byte) 0x22, "urn:epc:"); 51 | URI_PREFIX_MAP.put((byte) 0x23, "urn:nfc:"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/nfc_read.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/drawable/nfc_read.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/nfc_run.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/drawable/nfc_run.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable/nfc_write.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/drawable/nfc_write.jpg -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_read_mu.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_read_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 27 | 28 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_read_uri.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 27 | 28 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_run_app.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_run_url.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_write_mu.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 26 | 27 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_write_text.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 25 | 26 | 34 | 35 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_write_uri.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 19 | 25 | 26 | 34 | 35 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #FFFFFF 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Nfc 3 | 自动打开短信界面 4 | 自动打开百度页面 5 | 读NFC标签中的文本数据 6 | 写NFC标签中的文本数据 7 | 读NFC标签中的Uri数据 8 | 写NFC标签中的Uri数据 9 | 读NFC标签非NDEF格式的数据 10 | 写NFC标签非NDEF格式的数据 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/ricky/nfc/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.ricky.nfc; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.3.3' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | 21 | task clean(type: Delete) { 22 | delete rootProject.buildDir 23 | } 24 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RickyYu/Nfc-Android/c855e746e4380aaf2cb6d451e8a06f3186b9bea6/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Aug 24 16:56:36 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------