如何在屏幕固定时通过 NFC 发送字符串?
How can I send a string through NFC while Screen-Pinning?
我正在尝试通过 NFC 发送 String
,而我的应用正在使用 screen pinning。它不起作用:转移没有发生;但是如果我禁用屏幕固定 String
的传输。
我可以稍微禁用屏幕固定,然后执行传输,但这是一个安全风险。
我该怎么做?
如果您想尝试,这里是所有代码。您需要做的就是通过您的应用程序设置手动启用屏幕固定(因此它的代码更少并且仍然产生相同的结果)。我使用两个 Nexus 7 测试了这个 运行 Android 5.0.
你不必阅读所有这些代码,如果你知道我可以添加到我的清单中的东西,在屏幕固定时允许 NFC,这个问题可能会得到解决。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidnfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.NFC"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidnfc.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
public class MainActivity extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback
{
TextView textInfo;
EditText textOut;
NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textInfo = (TextView)findViewById(R.id.info);
textOut = (EditText)findViewById(R.id.textout);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.setNdefPushMessageCallback(this, this);
nfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
@Override
protected void onResume()
{
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
{
Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
NdefRecord NdefRecord_0 = inNdefRecords[0];
String inMsg = new String(NdefRecord_0.getPayload());
textInfo.setText(inMsg);
}
}
@Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
}
@Override
public void onNdefPushComplete(NfcEvent event) {
final String eventString = "onNdefPushComplete\n" + event.toString();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), eventString, Toast.LENGTH_LONG).show();
}
});
}
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
String stringOut = textOut.getText().toString();
byte[] bytesOut = stringOut.getBytes();
NdefRecord ndefRecordOut = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA,
"text/plain".getBytes(),
new byte[] {},
bytesOut);
NdefMessage ndefMessageout = new NdefMessage(ndefRecordOut);
return ndefMessageout;
}
}
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androidnfc.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textStyle="bold" />
<EditText
android:id="@+id/textout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
我不确定这是否真的回答了你的问题,但我想总结一下我的发现:
在 Android 5.0.1(Nexus 4 上的 LRX22C)上尝试您的示例时,接收方在收到 NDEF 消息后自动取消固定屏幕并(重新)启动 activity。因此,似乎在清单中注册的 Intent 过滤器优先于(手动?)屏幕固定。
我知道这与问题中描述的体验不太相符。我想知道这是否是由于 Android 版本不同( 5.0 与 5.0.1) 或由于使用手动屏幕固定而不是程序屏幕固定...
在我的测试设置中,我能够通过使用前台调度系统注册 activity 来接收它的 NDEF 消息来解决问题(即防止 activity 自动取消固定) :
在您的 onResume()
方法中创建一个像这样的待定意图并启用前台调度:
PendingIntent pi = this.createPendingResult(0x00A, new Intent(), 0);
nfcAdapter.enableForegroundDispatch(this, pi, null, null);
然后您将通过 activity 的 onActivityResult()
方法收到有关已发现标签的通知:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 0x00A:
onNewIntent(data);
break;
}
}
此外,您必须在 onPause()
方法中禁用前台调度:
nfcAdapter.disableForegroundDispatch(this);
我正在尝试通过 NFC 发送 String
,而我的应用正在使用 screen pinning。它不起作用:转移没有发生;但是如果我禁用屏幕固定 String
的传输。
我可以稍微禁用屏幕固定,然后执行传输,但这是一个安全风险。
我该怎么做?
如果您想尝试,这里是所有代码。您需要做的就是通过您的应用程序设置手动启用屏幕固定(因此它的代码更少并且仍然产生相同的结果)。我使用两个 Nexus 7 测试了这个 运行 Android 5.0.
你不必阅读所有这些代码,如果你知道我可以添加到我的清单中的东西,在屏幕固定时允许 NFC,这个问题可能会得到解决。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidnfc"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="19" />
<uses-permission android:name="android.permission.NFC"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.androidnfc.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
public class MainActivity extends Activity implements CreateNdefMessageCallback, OnNdefPushCompleteCallback
{
TextView textInfo;
EditText textOut;
NfcAdapter nfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textInfo = (TextView)findViewById(R.id.info);
textOut = (EditText)findViewById(R.id.textout);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
nfcAdapter.setNdefPushMessageCallback(this, this);
nfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
@Override
protected void onResume()
{
super.onResume();
Intent intent = getIntent();
String action = intent.getAction();
if(action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
{
Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage inNdefMessage = (NdefMessage)parcelables[0];
NdefRecord[] inNdefRecords = inNdefMessage.getRecords();
NdefRecord NdefRecord_0 = inNdefRecords[0];
String inMsg = new String(NdefRecord_0.getPayload());
textInfo.setText(inMsg);
}
}
@Override
protected void onNewIntent(Intent intent) {
setIntent(intent);
}
@Override
public void onNdefPushComplete(NfcEvent event) {
final String eventString = "onNdefPushComplete\n" + event.toString();
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(getApplicationContext(), eventString, Toast.LENGTH_LONG).show();
}
});
}
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
String stringOut = textOut.getText().toString();
byte[] bytesOut = stringOut.getBytes();
NdefRecord ndefRecordOut = new NdefRecord(
NdefRecord.TNF_MIME_MEDIA,
"text/plain".getBytes(),
new byte[] {},
bytesOut);
NdefMessage ndefMessageout = new NdefMessage(ndefRecordOut);
return ndefMessageout;
}
}
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical"
tools:context="com.example.androidnfc.MainActivity" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:textStyle="bold" />
<EditText
android:id="@+id/textout"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
我不确定这是否真的回答了你的问题,但我想总结一下我的发现:
在 Android 5.0.1(Nexus 4 上的 LRX22C)上尝试您的示例时,接收方在收到 NDEF 消息后自动取消固定屏幕并(重新)启动 activity。因此,似乎在清单中注册的 Intent 过滤器优先于(手动?)屏幕固定。
我知道这与问题中描述的体验不太相符。我想知道这是否是由于 Android 版本不同( 5.0 与 5.0.1) 或由于使用手动屏幕固定而不是程序屏幕固定...
在我的测试设置中,我能够通过使用前台调度系统注册 activity 来接收它的 NDEF 消息来解决问题(即防止 activity 自动取消固定) :
在您的 onResume()
方法中创建一个像这样的待定意图并启用前台调度:
PendingIntent pi = this.createPendingResult(0x00A, new Intent(), 0);
nfcAdapter.enableForegroundDispatch(this, pi, null, null);
然后您将通过 activity 的 onActivityResult()
方法收到有关已发现标签的通知:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 0x00A:
onNewIntent(data);
break;
}
}
此外,您必须在 onPause()
方法中禁用前台调度:
nfcAdapter.disableForegroundDispatch(this);